class CategoriesGeneral(): ADD_CATEGORY_BUTTON = "Add Category Button" MERGE_CATEGORIES_BUTTON = "Merge Categories Button" CATEGORY_ITEM = "Category Item" CATEGORY_INFO = '//android.view.ViewGroup[@content-desc="Category Item"]/android.view.ViewGroup' CONFIRM_MERGE_BUTTON = "Merge" # TYPE EXPENSES = "Expenses" INCOME = "Income" def __init__(self, driver): self.driver = driver self.ew = ElementWrapper(self.driver) def set_type(self, type_of_category): """ Selects income or expense set of categories :param type_of_category: str """ if type_of_category == "random": type_of_category = random.choice([self.EXPENSES, self.INCOME]) elif type_of_category == "expenses": type_of_category = self.EXPENSES else: type_of_category = self.INCOME self.ew.wait_and_tap_element(type_of_category, 5)
def __init__(self, driver): self.driver = driver self.action = TouchAction(self.driver) self.categories_general = CategoriesGeneral(self.driver) self.category_detail = CategoryDetail(self.driver) self.ew = ElementWrapper(self.driver) self.rs = Resolutions(self.driver)
def __init__(self, driver): self.driver = driver self.action = TouchAction(self.driver) self.ew = ElementWrapper(self.driver) self.period_filter = PeriodFilter(self.driver) self.rs = Resolutions(self.driver) self.timeline_general = TimelineGeneral(self.driver) self.transaction_detail = TransactionDetail(self.driver)
def __init__(self, driver): self.driver = driver self.action = TouchAction(self.driver) self.ew = ElementWrapper(self.driver) self.rs = Resolutions(self.driver) self.wallets_general = WalletsGeneral(self.driver) self.wallet_detail = WalletDetail(self.driver) self.wallets_overview = WalletOverview(self.driver)
def __init__(self, driver): self.driver = driver self.action = TouchAction(self.driver) self.budget_detail = BudgetDetail(self.driver) self.budgets_general = BudgetsGeneral(self.driver) self.budget_overview = BudgetOverview(self.driver) self.ew = ElementWrapper(self.driver) self.rs = Resolutions(self.driver) self.transaction_detail = TransactionDetail(self.driver)
def __init__(self, driver): self.driver = driver self.ew = ElementWrapper(self.driver) self.email_password = EmailPassword(self.driver) self.facebook = Facebook(self.driver) self.google = Google(self.driver) self.marketing_dialog = MarketingDialog(self.driver) self.more_general = MoreGeneral(self.driver) self.timeline_general = TimelineGeneral(self.driver) self.user_profile = UserProfile(self.driver) self.welcome_screen = WelcomeScreen(self.driver)
class AdvancedGeneral: ADVANCED_HEADER = "Advanced Header" EXPORT = "Export" def __init__(self, driver): self.driver = driver self.ew = ElementWrapper(self.driver) self.export_general = ExportGeneral(self.driver) def go_to_export(self): """Opens export screen""" self.ew.wait_and_tap_element(self.EXPORT, 10) self.ew.wait_till_element_is_visible(self.export_general.EXPORT_HEADER, 10)
class MainCurrency: CURRENCY_PICKER = "Select currency Picker" if PLATFORM == "Android": SELECTED_CURRENCY = '//android.view.ViewGroup[@content-desc="Main Currency"]/android.view.ViewGroup/android.widget.TextView[2]' else: SELECTED_CURRENCY = 'label == "Main Currency"' def __init__(self, driver): self.driver = driver self.ew = ElementWrapper(self.driver) def set_currency(self, currency): """ Selecting main currency of user :param currency: str """ if currency == "random": currency = random.choice(vs.accessible_currencies) self.ew.wait_and_tap_element(f"Currency {currency}", 10) self.ew.wait_till_element_is_not_visible(self.CURRENCY_PICKER, 10) def get_currency(self): """ Getting selected main currency :return: str """ self.ew.wait_till_element_is_visible(self.SELECTED_CURRENCY, 10) if PLATFORM == "Android": return self.ew.get_text_of_element(self.SELECTED_CURRENCY) else: return self.ew.get_attribute(self.SELECTED_CURRENCY, "name")
class EmailPassword: EMAIL_INPUT = "Email Input" PASSWORD_INPUT = "Password Input" EXISTING_EMAIL_DIALOG = "Email Already In Use Dialog" LOGIN_BUTTON = "Login Button" SIGN_UP_BUTTON = "Sign Up Button" INVALID_CREDENTIALS_DIALOG = "Invalid Credentials Dialog" VALIDATION_ERROR_WARNING = "Validation Error Warning" def __init__(self, driver): self.driver = driver self.ew = ElementWrapper(self.driver) def set_email(self, email): """ Inserts email of user into email input :param email: str """ self.ew.wait_till_element_is_visible(self.EMAIL_INPUT, 5) self.ew.get_element(self.EMAIL_INPUT).send_keys(email) def set_password(self, password): """ Inserts password of user into password input :param password: str """ self.ew.wait_till_element_is_visible(self.PASSWORD_INPUT, 5) self.ew.get_element(self.PASSWORD_INPUT).send_keys(password)
class BankSearchScreen(): SEARCH_INPUT = "Search Input" if PLATFORM == "Android": BANK_ITEM = "Bank Item" else: BANK_ITEM = 'label == "Bank Item"' BACK_BUTTON = "Back Button" def __init__(self, driver): self.driver = driver self.ew = ElementWrapper(self.driver) def search_bank_by_search_box(self, bank): """ Searches for a bank via search textbox :param bank: str """ if bank == "random": bank = "Fake Bank Simple" self.ew.get_element(self.SEARCH_INPUT).send_keys(bank) if PLATFORM == "Android": self.ew.wait_till_element_is_visible(bank, 15) else: self.ew.wait_till_element_is_visible( f'label == "Bank Item" AND name == "{bank}"', 15) if self.driver.is_keyboard_shown(): self.driver.hide_keyboard() self.ew.wait_and_tap_element(self.BANK_ITEM, 15)
class BankAccountsGeneral(): CONNECT_BANK_ACCOUNT_BUTTON = "Connect Bank Account Button" BACK_BUTTON = "Back Button" if PLATFORM == "Android": BANK_ITEM = "Bank Item" BANK_ITEM_NAME = '//android.view.ViewGroup[@content-desc="Bank Item"]/android.widget.TextView' else: BANK_ITEM = '**/XCUIElementTypeOther[`label == "Bank Item"`][3]' def __init__(self, driver): self.driver = driver self.ew = ElementWrapper(self.driver) def open_bank_account(self): """Opens bank account settings""" self.ew.wait_and_tap_element(self.BANK_ITEM, 15)
class WalletsGeneral: NAVIGATION_WALLETS = "Navigation Wallets" WALLETS_ANIMATED_HEADER = "Wallets Animated Header" ADD_WALLET_BUTTON = "Add Wallet Button" CONNECT_BANK_BUTTON = "Connect Bank Button" if PLATFORM == "Android": WALLET_ITEM = '//android.widget.ScrollView[@content-desc="Wallets List"]/android.view.ViewGroup/android.view.ViewGroup[1]' else: WALLET_ITEM = '(//XCUIElementTypeOther[@name="Wallets List"])[2]/XCUIElementTypeScrollView//XCUIElementTypeOther//XCUIElementTypeOther' def __init__(self, driver): self.driver = driver self.ew = ElementWrapper(self.driver) def go_to_wallets(self): """Opens Wallets navigation section""" self.ew.wait_and_tap_element(self.NAVIGATION_WALLETS, 30) self.ew.wait_till_element_is_visible(self.WALLETS_ANIMATED_HEADER, 30)
class TransferOriginationModal(): ORIGINATION_MODAL = "Transfer Origination" DESTINATION_MODAL = "Transfer Destination" CONFIRM_BUTTON = "Confirm Button" def __init__(self, driver): self.driver = driver self.ew = ElementWrapper(self.driver) self.transaction_detail = TransactionDetail(self.driver) def create_as_new_transaction(self): """Clicking on button 'Create as new transaction'""" self.ew.tap_element(self.CONFIRM_BUTTON) def is_origination_modal_present(self): """ Check if modal is present :return: bool """ self.ew.wait_till_element_is_not_visible( self.transaction_detail.SAVE_TRANSACTION_BUTTON, 10) if self.ew.is_element_present(self.ORIGINATION_MODAL): return True else: return False
class BankAccountDetail(): CONSENT = "Consent" CONSENT_WEBVIEW = "Spendee" REMOVE_BUTTON = "Remove Button" REMOVE_CONFIRM = "Remove" EYE_ICON = "Eye Icon-true" BACK_BUTTON = "Back Button" def __init__(self, driver): self.driver = driver self.ew = ElementWrapper(self.driver) def open_consent(self): """Opens consent screen""" self.ew.wait_and_tap_element(self.CONSENT, 15) self.ew.wait_till_element_is_not_visible(self.CONSENT, 10) def disconnect_bank_account(self): """Removes bank connection""" self.ew.wait_and_tap_element(self.REMOVE_BUTTON, 15) self.ew.wait_and_tap_element(self.REMOVE_CONFIRM, 5) self.ew.wait_till_element_is_not_visible(self.REMOVE_CONFIRM, 10) def hide_bank_wallets(self, wallets): """ Hides requested number of bank wallets of 1 bank connection :param wallets: int :return: """ if wallets == "random": wallets = random.randint(1, 3) x = 0 all_wallets = self.ew.get_elements(self.EYE_ICON) for i in all_wallets: x = x + 1 if x <= wallets: i.click()
class BudgetValidator: def __init__(self, driver): self.driver = driver self.action = TouchAction(self.driver) self.budget_detail = BudgetDetail(self.driver) self.budgets_general = BudgetsGeneral(self.driver) self.budget_overview = BudgetOverview(self.driver) self.ew = ElementWrapper(self.driver) self.rs = Resolutions(self.driver) self.transaction_detail = TransactionDetail(self.driver) def get_all_attributes(self): """ Getting all attributes of budget :return: dict """ all_attributes = { "name": self.budget_detail.get_name(), "amount": self.budget_detail.get_amount(), "currency": self.budget_detail.get_currency(), "wallets": self.budget_detail.get_wallets(), "categories": self.budget_detail.get_categories(), "recurrence": self.budget_detail.get_recurrence(), "start_date": self.transaction_detail.get_date("start"), "end_date": self.transaction_detail.get_date("end") } return all_attributes def is_budget_existing(self, attributes): """ Checking if budget is visible inside Budgets section :param attributes: dict :return: bool """ budget_locator = f"{attributes['name']}/" \ f"{attributes['amount']}/" \ f"{attributes['currency']}/" \ f"{self.adjust_wallets(attributes['wallets'])}/" \ f"{self.adjust_categories(attributes['categories'])}/" \ f"{self.adjust_recurrence(attributes['recurrence'])}/" \ f"{attributes['start_date']}/" \ f"{self.adjust_end_date(attributes['end_date'], attributes['start_date'], attributes['recurrence'])}" print(f'ATTRIBUTES: {attributes}') print(f'LOCATOR: {budget_locator}') if self.ew.is_element_present(self.budget_overview.OVERVIEW_BUTTON): self.ew.tap_element(self.budget_overview.BACK_BUTTON) self.ew.wait_till_element_is_visible( self.budgets_general.BUDGETS_HEADER, 10) android_timeout = time.time() + 30 ios_timeout = time.time() + 5 res = self.rs.get_resolution() is_budget_present = self.ew.is_element_present(budget_locator) while is_budget_present is False: if PLATFORM == "Android": self.action.long_press(None, self.rs.all_resolutions[f"{res}"]["x"], self.rs.all_resolutions[f"{res}"]["budget_overview_y_start"]) \ .move_to(None, self.rs.all_resolutions[f"{res}"]["x"], self.rs.all_resolutions[f"{res}"]["budget_overview_y_end"]) \ .release().perform() is_budget_present = self.ew.is_element_present(budget_locator) if time.time() > android_timeout: return False else: is_budget_present = self.ew.is_element_present(budget_locator) if time.time() > ios_timeout: return False return True def adjust_wallets(self, wallets): """ Adjusting wallets for budget locator :param wallets: str :return: str """ if wallets == "All Wallets": return "undefined" elif wallets in ["0", "2", "3", "4", "5", "6", "7", "8", "9", "10"]: return wallets else: return "1" def adjust_categories(self, categories): """ Adjusting categories for budget locator :param categories: str :return: str """ if categories == "All Expenses": return "undefined" else: return categories def adjust_recurrence(self, recurrence): """ Adjusting recurrence for recurrence locator :param recurrence: str :return: str """ recurrences_in_app = [ "once", "day", "week", "every two weeks", "month", "year" ] return recurrences_in_app[vs.budget_recurrences.index(recurrence)] def adjust_end_date(self, end_date, start_date, recurrence): """ Adjusting end date for budget locator :param end_date: str :param start_date: str :param recurrence: str :return: str """ if end_date is None: year_start, month_start, day_start = ( int(x) for x in start_date.split('-')) start_date = datetime.date(year_start, month_start, day_start) if (year_start % 4) == 0: if (year_start % 100) == 0: if (year_start % 400) == 0: is_year_leap = True else: is_year_leap = False else: is_year_leap = True else: is_year_leap = False if recurrence == "Daily": end_date = start_date elif recurrence == "Weekly": end_date = str(start_date + datetime.timedelta(days=6)) elif recurrence == "Biweekly": end_date = str(start_date + datetime.timedelta(days=13)) elif recurrence == "Monthly": if month_start in ["01", "03", "05", "07", "08", "10", "12"]: end_date = str(start_date + datetime.timedelta(days=30)) elif month_start in ["04", "06", "09", "11"]: end_date = str(start_date + datetime.timedelta(days=29)) else: if is_year_leap: end_date = str(start_date + datetime.timedelta(days=28)) else: end_date = str(start_date + datetime.timedelta(days=27)) elif recurrence == "Yearly": if is_year_leap: end_date = str(start_date + datetime.timedelta(days=365)) else: end_date = str(start_date + datetime.timedelta(days=364)) return end_date
class WalletsActions: def __init__(self, driver): self.driver = driver self.action = TouchAction(self.driver) self.ew = ElementWrapper(self.driver) self.rs = Resolutions(self.driver) self.wallets_general = WalletsGeneral(self.driver) self.wallet_detail = WalletDetail(self.driver) self.wallets_overview = WalletOverview(self.driver) def create_wallet(self, name, amount, currency, categories): """ Opens wallet create screen and sets requested attributes :param name: str or None :param amount: str or None :param currency: str or None :param categories: str or int or None """ self.wallets_general.go_to_wallets() self.open_wallet_create_screen() self.wallet_detail.set_name(name) if amount is not None: self.wallet_detail.set_amount(amount) if currency is not None: self.wallet_detail.set_currency(currency) if categories is not None: self.wallet_detail.set_categories(categories) def open_wallet_create_screen(self): """Opens wallet create screen""" self.ew.wait_till_element_is_visible( self.wallets_general.WALLETS_ANIMATED_HEADER, 10) if PLATFORM == "Android": add_button_visible = self.ew.is_element_present( self.wallets_general.ADD_WALLET_BUTTON) while add_button_visible is False: res = self.rs.get_resolution() self.action.long_press(None, self.rs.all_resolutions[f"{res}"]["x"], self.rs.all_resolutions[f"{res}"]["wallets_overview_y_start"]) \ .move_to(None, self.rs.all_resolutions[f"{res}"]["x"], self.rs.all_resolutions[f"{res}"]["wallets_overview_y_end"]) \ .release().perform() add_button_visible = self.ew.is_element_present( self.wallets_general.ADD_WALLET_BUTTON) else: add_button_visible = self.ew.get_attribute( self.wallets_general.ADD_WALLET_BUTTON, "visible") while add_button_visible == "false": res = self.rs.get_resolution() self.driver.execute_script( "mobile: dragFromToForDuration", { "duration": "0.1", "fromX": self.rs.all_resolutions[f"{res}"]["x"], "fromY": self.rs.all_resolutions[f"{res}"] ["wallets_overview_y_start"], "toX": self.rs.all_resolutions[f"{res}"]["x"], "toY": self.rs.all_resolutions[f"{res}"] ["wallets_overview_y_end"] }) add_button_visible = self.ew.get_attribute( self.wallets_general.ADD_WALLET_BUTTON, "visible") self.ew.wait_and_tap_element(self.wallets_general.ADD_WALLET_BUTTON, 5) self.ew.wait_till_element_is_visible(self.wallet_detail.WALLET_HEADER, 10) def save_wallet(self): """Clicks on save wallet button""" if self.driver.is_keyboard_shown(): self.driver.hide_keyboard() self.ew.wait_and_tap_element(self.wallet_detail.SAVE_WALLET_BUTTON, 10) self.ew.wait_till_element_is_not_visible( self.wallet_detail.SAVE_WALLET_BUTTON, 10) def open_wallet(self): """Opens existing wallet""" self.wallets_general.go_to_wallets() self.ew.wait_till_element_is_visible( self.wallets_general.WALLETS_ANIMATED_HEADER, 10) self.ew.wait_and_tap_element(self.wallets_general.WALLET_ITEM, 5) self.ew.wait_and_tap_element(self.wallets_overview.EDIT_BUTTON, 5) self.ew.wait_till_element_is_visible(self.wallet_detail.WALLET_HEADER, 5) def edit_wallet(self, name, amount, currency, categories): """Changes requested attributes of wallet :param name: str or None :param amount: str or None :param currency: str or None :param categories: str or int or None """ self.open_wallet() if name is not None: if PLATFORM == "Android": self.ew.get_element(self.wallet_detail.NAME_INPUT).clear() else: self.ew.get_element( self.wallet_detail.SELECTED_NAME_IOS).clear() self.wallet_detail.set_name(name) if amount is not None: self.ew.wait_and_tap_element(self.wallet_detail.AMOUNT_INPUT, 5) self.ew.wait_till_element_is_visible( self.wallet_detail.NUMPAD_CLEAR, 10) for i in range(6): self.ew.tap_element(self.wallet_detail.NUMPAD_CLEAR) self.ew.tap_element(self.wallet_detail.NUMPAD_BACKDROP) self.wallet_detail.set_amount(amount) if currency is not None: self.wallet_detail.set_currency(currency) if categories is not None: self.wallet_detail.set_categories(categories) def delete_wallet(self): """Deletes wallet from wallet detail""" self.ew.wait_and_tap_element(self.wallet_detail.TRASH_ICON, 10) self.ew.wait_and_tap_element(self.wallet_detail.DELETE_BUTTON, 10) self.ew.wait_till_element_is_visible( self.wallets_general.WALLETS_ANIMATED_HEADER, 10) def invite_user_to_wallet(self): """Opens wallet and invitation screen""" self.open_wallet() self.wallet_detail.invite_user()
class BudgetDetail(): # OTHER BUDGET_HEADER = "Budget Header" SAVE_BUDGET_BUTTON = "Save Budget Button" TRASH_ICON = "Trash Icon" DELETE_BUTTON = "Delete" if PLATFORM == "Android": DISCARD_CHANGES = "android:id/button1" else: DISCARD_CHANGES = "Discard changes" # NAME NAME_INPUT = "Name Input" SELECTED_NAME_IOS = '**/XCUIElementTypeTextField[`label == "Name Input"`]' # AMOUNT if PLATFORM == "Android": AMOUNT_INPUT = "Amount Input" else: AMOUNT_INPUT = '**/XCUIElementTypeOther[`label == "Amount Input"`][2]' SELECTED_AMOUNT = "Currency Input" # KEYBOARD KEYBOARD = {"0": "Numpad 0", "1": "Numpad 1", "2": "Numpad 2", "3": "Numpad 3", "4": "Numpad 4", "5": "Numpad 5", "6": "Numpad 6", "7": "Numpad 7", "8": "Numpad 8", "9": "Numpad 9", ".": "Numpad Decimal Point", ",": "Numpad Decimal Point"} NUMPAD_BACKDROP = "Numpad Backdrop" NUMPAD_CLEAR = "Numpad Clear" # CURRENCY CURRENCY = "Currency" if PLATFORM == "Android": SELECTED_CURRENCY = '//android.view.ViewGroup[@content-desc="Currency"]/android.view.ViewGroup/android.view.ViewGroup/android.widget.EditText' CURRENCY_PICKER = "Select currency Picker" else: SELECTED_CURRENCY = '**/XCUIElementTypeOther[`label == "Currency"`][1]' CURRENCY_PICKER = 'label == "Select currency"' # WALLETS if PLATFORM == "Android": WALLET_ITEM = '//android.view.ViewGroup[@content-desc="Select Wallets Picker"]/android.widget.ScrollView/android.view.ViewGroup/android.view.ViewGroup/android.view.ViewGroup' WALLETS = "Wallets" else: WALLET_ITEM = "Wallet Item" WALLETS = 'label == "Wallets"' WALLET_PICKER = "Select Wallets Picker" SELECTED_WALLETS_ANDROID = '//android.view.ViewGroup[@content-desc="Wallets"]/android.view.ViewGroup/android.widget.TextView[2]' SELECTED_WALLETS_ANDROID_2 = '//android.view.ViewGroup[@content-desc="Wallets"]/android.widget.TextView[2]' # CATEGORIES CATEGORIES = "Categories" HEADER_BUDGET_FOR = "Header Budget For" SELECT_ALL_CHECKED = "Select All-checked" SELECT_ALL_UNCHECKED = "Select All-unchecked" SELECT_ALL_PART = "Select All-part" if PLATFORM == "Android": CATEGORIES = "Categories" CATEGORY_ITEM = '//android.view.ViewGroup[@content-desc="Category Item"]/android.view.ViewGroup' SELECTED_CATEGORIES_ANDROID = '//android.view.ViewGroup[@content-desc="Categories"]/android.widget.TextView[2]' SELECTED_CATEGORIES_ANDROID_2 = '//android.view.ViewGroup[@content-desc="Categories"]/android.view.ViewGroup/android.widget.TextView[2]' else: CATEGORY_ITEM = 'label == "Category Item"' CATEGORIES = 'label == "Categories"' BACK_BUTTON = "Back Button" # RECURRENCE if PLATFORM == "Android": RECURRENCE = "Recurrence" SELECTED_RECURRENCE_ANDROID = '//android.view.ViewGroup[@content-desc="Recurrence"]/android.widget.TextView[2]' SELECTED_RECURRENCE_ANDROID_EDIT = '//android.view.ViewGroup[@content-desc="Recurrence"]/android.view.ViewGroup/android.widget.TextView[2]' else: RECURRENCE = 'label == "Recurrence"' RECURRENCE_PICKER = "Recurrence Picker" # START DATE if PLATFORM == "Android": START_DATE = "Start Date" else: START_DATE = 'label == "Start Date"' CALENDAR_PICKER = "Select date Picker" # END DATE if PLATFORM == "Android": END_DATE = "End Date" else: END_DATE = 'label == "End Date"' def __init__(self, driver): self.driver = driver self.action = TouchAction(self.driver) self.ew = ElementWrapper(self.driver) self.rs = Resolutions(self.driver) self.transaction_detail = TransactionDetail(self.driver) def set_name(self, name): """ Insert name into name input :param name: str """ if name == "random": name = ''.join([random.choice(string.ascii_lowercase + string.digits) for n in range(0, 8)]) self.ew.wait_till_element_is_visible(self.NAME_INPUT, 5) self.ew.get_element(self.NAME_INPUT).send_keys(name) vr.validate_input_against_output(name, self.get_name()) def get_name(self): """ Gets name of budget from name input :return: str """ self.ew.wait_till_element_is_visible(self.NAME_INPUT, 5) if PLATFORM == "Android": return self.ew.get_text_of_element(self.NAME_INPUT) else: return self.ew.get_text_of_element(self.SELECTED_NAME_IOS) def set_amount(self, amount): """ Insert amount into amount input :param amount: str """ if amount == "random": amount = str(random.randint(1, 99)) self.ew.wait_and_tap_element(self.AMOUNT_INPUT, 5) self.ew.wait_till_element_is_visible(self.KEYBOARD["1"], 10) amount_list = list(amount) for i in amount_list: self.ew.wait_and_tap_element(self.KEYBOARD[i], 5) self.ew.wait_and_tap_element(self.NUMPAD_BACKDROP, 5) vr.validate_input_against_output(amount, self.get_amount()) def get_amount(self): """ Gets amount of budget from amount input :return: str """ self.ew.wait_till_element_is_visible(self.AMOUNT_INPUT, 5) if PLATFORM == "Android": return self.ew.get_text_of_element(self.SELECTED_AMOUNT) else: return self.ew.get_attribute(self.AMOUNT_INPUT, "name") def set_currency(self, currency): """ Selects currency of budget :param currency: str """ if currency == "random": currency = random.choice(vs.accessible_currencies) self.ew.wait_and_tap_element(self.CURRENCY, 5) self.ew.wait_till_element_is_visible(self.CURRENCY_PICKER, 10) self.ew.wait_and_tap_element(f"Currency {currency}", 10) self.ew.wait_till_element_is_not_visible(self.CURRENCY_PICKER, 10) vr.validate_input_against_output(currency, self.get_currency()) def get_currency(self): """ Gets selected currency of budget :return: str """ self.ew.wait_till_element_is_visible(self.CURRENCY, 5) if PLATFORM == "Android": return self.ew.get_text_of_element(self.SELECTED_CURRENCY) else: return self.ew.get_attribute(self.SELECTED_CURRENCY, "name") def set_wallets(self, wallets): """ Selects wallets from wallets picker :param wallets: str or int """ self.ew.wait_and_tap_element(self.WALLETS, 5) self.ew.wait_till_element_is_visible(self.WALLET_PICKER, 5) all_visible_wallets = self.count_wallets()[0] selected_wallets = self.count_wallets()[1] non_selected_wallets = self.count_wallets()[2] total_wallets = len(all_visible_wallets) total_selected_wallets = len(selected_wallets) total_non_selected_wallets = len(non_selected_wallets) if wallets == "random": wallets_to_select = random.sample(all_visible_wallets, random.randrange(0, len(all_visible_wallets))) for i in wallets_to_select: if PLATFORM == "Android": self.ew.tap_element(i) else: self.ew.tap_element(f'label == "{i}"') elif wallets == "all_selected": if total_wallets != total_selected_wallets: for i in non_selected_wallets: if PLATFORM == "Android": self.ew.tap_element(i) else: self.ew.tap_element(f'label == "{i}"') elif wallets == "all_unselected": if total_wallets != total_non_selected_wallets: for i in selected_wallets: if PLATFORM == "Android": self.ew.tap_element(i) else: self.ew.tap_element(f'label == "{i}"') elif isinstance(wallets, int): x = 0 actual_selected_wallets = self.count_wallets()[1] for i in all_visible_wallets: x = x + 1 if x <= wallets and len(actual_selected_wallets) > 1: if PLATFORM == "Android": self.ew.tap_element(i) else: self.ew.tap_element(f'label == "{i}"') actual_selected_wallets = self.count_wallets()[1] selected_wallets = self.count_wallets()[1] total_wallets = len(self.count_wallets()[0]) total_selected_wallets = len(selected_wallets) if total_wallets == total_selected_wallets: v_input = "All Wallets" elif total_selected_wallets == 1: v_input = selected_wallets[0].split('-')[0] else: v_input = str(total_selected_wallets) self.ew.tap_element('Backdrop') vr.validate_input_against_output(v_input, self.get_wallets()) def count_wallets(self): """ Gets all visible wallets, currently selected wallets and not_selected wallets from wallets picker :return: tuple of lists """ if PLATFORM == "Android": all_visible_wallets = self.ew.get_attributes(self.WALLET_ITEM, "content-desc") else: all_visible_wallets = self.ew.get_attributes(self.WALLET_ITEM, "label") selected_wallets = [] non_selected_wallets = [] for i in all_visible_wallets: if i.endswith('true'): selected_wallets.append(i) else: non_selected_wallets.append(i) return (all_visible_wallets, selected_wallets, non_selected_wallets) def get_wallets(self): """ Gets selected wallets (number, name or 'All Wallets') :return: str """ self.ew.wait_till_element_is_visible(self.WALLETS, 5) if PLATFORM == "Android": result = self.ew.get_text_of_element(self.SELECTED_WALLETS_ANDROID) if result is None: result = self.ew.get_text_of_element(self.SELECTED_WALLETS_ANDROID_2) else: result = self.ew.get_attribute(self.WALLETS, "name") return result def set_categories(self, categories): """ Selects requested number of categories :param categories: str """ self.ew.wait_and_tap_element(self.CATEGORIES, 5) self.ew.wait_till_element_is_visible(self.HEADER_BUDGET_FOR, 5) all_visible_categories = self.count_categories()[0] if categories == "random": categories = random.randrange(0, len(all_visible_categories)) if categories == "all_selected": if self.ew.is_element_present(self.SELECT_ALL_UNCHECKED): self.ew.tap_element(self.SELECT_ALL_UNCHECKED) elif self.ew.is_element_present(self.SELECT_ALL_PART): self.ew.tap_element(self.SELECT_ALL_PART) self.ew.tap_element(self.SELECT_ALL_UNCHECKED) elif categories == "all_unselected": if self.ew.is_element_present(self.SELECT_ALL_CHECKED): self.ew.tap_element(self.SELECT_ALL_CHECKED) elif self.ew.is_element_present(self.SELECT_ALL_PART): self.ew.tap_element(self.SELECT_ALL_PART) elif isinstance(categories, int): if self.ew.is_element_present(self.SELECT_ALL_CHECKED): self.ew.tap_element(self.SELECT_ALL_CHECKED) elif self.ew.is_element_present(self.SELECT_ALL_PART): self.ew.tap_element(self.SELECT_ALL_PART) x = 0 all_visible_categories = self.count_categories()[0] for i in all_visible_categories: x = x + 1 if x <= categories: self.ew.tap_element(i) if self.ew.is_element_present(self.SELECT_ALL_CHECKED): v_input = "All Expenses" else: v_input = str(len(self.count_categories()[1])) self.ew.tap_element(self.BACK_BUTTON) vr.validate_input_against_output(v_input, self.get_categories()) def count_categories(self): """ Gets all visible, currently selected and non selected categories inside category picker :return: tuple of lists """ if PLATFORM == "Android": all_visible_categories = self.ew.get_attributes(self.CATEGORY_ITEM, "content-desc") else: all_items = self.ew.get_attributes(self.CATEGORY_ITEM, "name") all_visible_categories = [] for i in all_items: if i != "Category Item": all_visible_categories.append(i) selected_categories = [] non_selected_categories = [] for i in all_visible_categories: if i.endswith('true'): selected_categories.append(i) else: non_selected_categories.append(i) return (all_visible_categories, selected_categories, non_selected_categories) def get_categories(self): """ Gets number of selected categories :return: str """ self.ew.wait_till_element_is_visible(self.CATEGORIES, 5) if PLATFORM == "Android": result = self.ew.get_text_of_element(self.SELECTED_CATEGORIES_ANDROID) if result is None: result = self.ew.get_text_of_element(self.SELECTED_CATEGORIES_ANDROID_2) return result else: return self.ew.get_attribute(self.CATEGORIES, "name") def set_recurrence(self, recurrence): """ Selects requested recurrence of budget :param recurrence: str """ self.ew.wait_and_tap_element(self.RECURRENCE, 5) self.ew.wait_till_element_is_visible(self.RECURRENCE_PICKER, 5) if recurrence == "random": recurrence = random.choice(vs.budget_recurrences) res = self.rs.get_resolution() if PLATFORM == "Android": item_visible = self.ew.is_element_present(recurrence) while item_visible is False: self.action.long_press(None, self.rs.all_resolutions[f"{res}"]["x"], self.rs.all_resolutions[f"{res}"]["default_picker_up_y_start"]) \ .move_to(None, self.rs.all_resolutions[f"{res}"]["x"], self.rs.all_resolutions[f"{res}"]["default_picker_up_y_end"]) \ .release().perform() item_visible = self.ew.is_element_present(recurrence) self.ew.wait_and_tap_element(recurrence, 5) else: item_visible = self.ew.get_attribute(recurrence, "visible") while item_visible == "false": self.driver.execute_script("mobile: dragFromToForDuration", {"duration": "0.1", "fromX": self.rs.all_resolutions[f"{res}"]["x"], "fromY": self.rs.all_resolutions[f"{res}"]["default_picker_up_y_start"], "toX": self.rs.all_resolutions[f"{res}"]["x"], "toY": self.rs.all_resolutions[f"{res}"]["default_picker_up_y_end"]}) item_visible = self.ew.get_attribute(recurrence, "visible") self.driver.execute_script("mobile: tap", {"x": 100, "y": 50, "element": self.ew.get_element(recurrence)}) vr.validate_input_against_output(recurrence, self.get_recurrence()) def get_recurrence(self): """ Gets selected recurrence :return: str """ self.ew.wait_till_element_is_visible(self.RECURRENCE, 5) if PLATFORM == "Android": recurrence = self.ew.get_text_of_element(self.SELECTED_RECURRENCE_ANDROID) if recurrence is None: recurrence = self.ew.get_text_of_element(self.SELECTED_RECURRENCE_ANDROID_EDIT) else: recurrence = self.ew.get_attribute(self.RECURRENCE, "name") return recurrence def set_start_date(self, start_date): """ Selects start date of budget :param start_date: str """ if start_date == "random": start_date = str( datetime.date(int(datetime.date.today().year), random.randint(1, 12), random.randint(1, 28))) elif start_date == "future": start_date = str(datetime.date.today() + datetime.timedelta(days=random.randint(1, 5))) elif start_date == "today": start_date = str(datetime.date.today()) elif start_date == "yesterday": start_date = str(datetime.date.today() - datetime.timedelta(days=1)) elif start_date == "tomorrow": start_date = str(datetime.date.today() + datetime.timedelta(days=1)) self.ew.wait_and_tap_element(self.START_DATE, 5) self.ew.wait_till_element_is_visible(self.CALENDAR_PICKER, 5) self.transaction_detail.set_calendar_month_year(start_date) self.transaction_detail.set_calendar_day(start_date) vr.validate_input_against_output(start_date, self.transaction_detail.get_date("start")) def set_end_date(self, end_date): """ Selects end date of budget :param end_date: str """ start_date = self.transaction_detail.get_date("start") year_start, month_start, day_start = (int(x) for x in start_date.split('-')) start_date = datetime.date(year_start, month_start, day_start) if end_date == "random": end_date = str(start_date + datetime.timedelta(days=random.randint(1, 30))) elif end_date == "day_after_start_date": end_date = str(start_date + datetime.timedelta(days=1)) else: year_end, month_end, day_end = (int(x) for x in end_date.split('-')) end_date = datetime.date(year_end, month_end, day_end) if start_date < end_date: end_date = str(end_date) else: raise ValueError(f"endDate {end_date} is not older than start_date {str(start_date)}") self.ew.wait_and_tap_element(self.END_DATE, 5) self.ew.wait_till_element_is_visible(self.CALENDAR_PICKER, 5) self.transaction_detail.set_calendar_month_year(end_date) self.transaction_detail.set_calendar_day(end_date) vr.validate_input_against_output(end_date, self.transaction_detail.get_date("end"))
class TransactionValidator: def __init__(self, driver): self.driver = driver self.action = TouchAction(self.driver) self.ew = ElementWrapper(self.driver) self.period_filter = PeriodFilter(self.driver) self.rs = Resolutions(self.driver) self.timeline_general = TimelineGeneral(self.driver) self.transaction_detail = TransactionDetail(self.driver) def get_all_attributes(self): """ Getting all attributes of transaction :return: dict """ all_attributes = { "category": self.transaction_detail.get_category(), "amount": self.transaction_detail.get_amount(), "wallet_amount": self.transaction_detail.get_wallet_amount(), "currency": self.transaction_detail.get_currency(), "wallet": self.transaction_detail.get_wallet("transaction"), "start_date": self.transaction_detail.get_date("start"), "note": self.transaction_detail.get_note(), "labels": self.transaction_detail.get_labels(True), "photo": self.transaction_detail.get_photo(), "reminder": self.transaction_detail.get_reminder(), } return all_attributes def is_transaction_on_timeline(self, attributes): """ Checking if transaction is visible inside Timeline or Scheduled section :param attributes: dict :return: bool """ transaction_locator = f"regular/" \ f"{attributes['category']}/" \ f"{self.adjust_amounts(attributes['amount'], attributes['wallet_amount'])[0]}/" \ f"{self.adjust_amounts(attributes['amount'], attributes['wallet_amount'])[1]}/" \ f"{attributes['wallet']}/" \ f"undefined/" \ f"{self.adjust_note(attributes['note'])}/" \ f"{self.adjust_labels(attributes['labels'])}/" \ f"{str(attributes['photo']).lower()}/" \ f"undefined/" \ f"undefined/" \ f"{self.adjust_reminder(attributes['reminder'])}" print(f'LOCATOR: {transaction_locator}') self.prepare_timeline(attributes['start_date'], "undefined") android_timeout = time.time() + 60 ios_timeout = time.time() + 5 res = self.rs.get_resolution() is_transaction_present = self.ew.is_element_present( transaction_locator) while is_transaction_present is False: if PLATFORM == "Android": self.swipe_android(res) is_transaction_present = self.ew.is_element_present( transaction_locator) if time.time() > android_timeout: return False else: is_transaction_present = self.ew.is_element_present( transaction_locator) if time.time() > ios_timeout: return False return True def adjust_amounts(self, amount, wallet_amount): """ Adjusting amount for transaction locator :param amount: str :param wallet_amount: str :return: list of str """ if wallet_amount is None: amount_final = amount wallet_amount_final = "undefined" else: amount_final = "" for i in wallet_amount: if i in [ "-", ".", "0", "1", "2", "3", "4", "5", "6", "7", "8", "9" ]: amount_final = amount_final + i wallet_amount_final = "{:.2f}".format(float(amount)) return ["{:.2f}".format(float(amount_final)), wallet_amount_final] def adjust_note(self, note): """ Adjusting note for transaction locator :param note: str :return: str """ if note is None: note = "" return note def adjust_labels(self, labels): """ Adjusting labels for transaction locator :param labels: list of str :return: list of str """ if len(labels) > 0: labels_final = "" for i in labels: labels_final = labels_final + f",{i}" labels_final = labels_final[1:] else: labels_final = "undefined" return labels_final def adjust_reminder(self, reminder): """ Adjusting reminder for transaction locator :param reminder: str :return: str """ if reminder is None or reminder == "Never": return "undefined" else: return reminder def prepare_timeline(self, start_date, recurrence): """ Prepares timeline for transaction search. Opening scheduled screen if transaction has future date. :param start_date: str :param recurrence: str """ self.ew.wait_till_element_is_visible( self.timeline_general.NAVIGATION_TIMELINE, 30) year, month, day = (int(x) for x in start_date.split('-')) date = datetime.date(year, month, day) today = datetime.date.today() if date > today or recurrence != "undefined": if self.ew.is_element_present( self.timeline_general.SCHEDULED_SCREEN) is False: self.ew.wait_till_element_is_visible( self.timeline_general.TRANSACTION_SECTION, 20) self.timeline_general.open_scheduled_section() else: if PLATFORM == "Android": time.sleep(5) else: time.sleep(2) elif date < today: self.period_filter.set_filter_period( self.period_filter.ALL_TIME_PERIOD) def swipe_android(self, resolution): """ Looks into past by swiping on android phones :param resolution: str :return: """ self.action.long_press(None, self.rs.all_resolutions[f"{resolution}"]["x"], self.rs.all_resolutions[f"{resolution}"]["transaction_timeline_up_y_start"]) \ .move_to(None, self.rs.all_resolutions[f"{resolution}"]["x"], self.rs.all_resolutions[f"{resolution}"]["transaction_timeline_up_y_end"]) \ .release().perform()
def __init__(self, driver): self.driver = driver self.ew = ElementWrapper(self.driver)
class ExportActions: BACKDROP = "Backdrop" # WALLETS WALLETS = "Wallets" # PERIOD PERIOD = "Period" PERIOD_SIZE_PICKER = "Period size Picker" SELECT_DATE_RANGE_PICKER = "Select date range Picker" # FORMAT FORMAT = "Format" FORMAT_PICKER = "Format Picker" if PLATFORM == "Android": XLSX_TRUE = "Excel (.xlsx)-true" else: XLSX_TRUE = 'label == "Excel (.xlsx)-true"' def __init__(self, driver): self.driver = driver self.action = TouchAction(self.driver) self.ew = ElementWrapper(self.driver) self.rs = Resolutions(self.driver) def set_period(self, period): """ Selects period from period picker :param period: str """ self.ew.wait_and_tap_element(self.PERIOD, 10) self.ew.wait_till_element_is_visible(self.PERIOD_SIZE_PICKER, 10) if period == "random": period = random.choice(vs.export_periods) res = self.rs.get_resolution() if PLATFORM == "Android": item_visible = self.ew.is_element_present(period) while item_visible is False: self.action.long_press(None, self.rs.all_resolutions[f"{res}"]["x"], self.rs.all_resolutions[f"{res}"]["default_picker_up_y_start"]) \ .move_to(None, self.rs.all_resolutions[f"{res}"]["x"], self.rs.all_resolutions[f"{res}"]["default_picker_up_y_end"]) \ .release().perform() item_visible = self.ew.is_element_present(period) self.ew.wait_and_tap_element(period, 5) else: item_visible = self.ew.get_attribute(period, "visible") while item_visible == "false": self.driver.execute_script( "mobile: dragFromToForDuration", { "duration": "0.1", "fromX": self.rs.all_resolutions[f"{res}"]["x"], "fromY": self.rs.all_resolutions[f"{res}"] ["default_picker_up_y_start"], "toX": self.rs.all_resolutions[f"{res}"]["x"], "toY": self.rs.all_resolutions[f"{res}"] ["default_picker_up_y_end"] }) item_visible = self.ew.get_attribute(period, "visible") self.driver.execute_script("mobile: tap", { "x": 100, "y": 50, "element": self.ew.get_element(period) }) def set_format(self, format): """ Selects format of file from format picker :param format: str """ self.ew.wait_and_tap_element(self.FORMAT, 10) self.ew.wait_till_element_is_visible(self.FORMAT_PICKER, 10) if format == "random": format = random.choice(vs.export_formats) self.ew.wait_and_tap_element(format, 5)
class BudgetActions(): def __init__(self, driver): self.driver = driver self.action = TouchAction(self.driver) self.budgets_general = BudgetsGeneral(self.driver) self.budget_detail = BudgetDetail(self.driver) self.budget_overview = BudgetOverview(self.driver) self.ew = ElementWrapper(self.driver) self.rs = Resolutions(self.driver) def create_budget(self, name, amount, currency, wallets, categories, recurrence, start_date, end_date): """ Opens budget create screen and sets requested attributes of budget :param name: str :param amount: str :param currency: str or None :param wallets: str or int or None :param categories: str or int or None :param recurrence: str or None :param start_date: str or None :param end_date: str or None """ self.budgets_general.go_to_budgets() self.open_budget_create_screen() self.budget_detail.set_name(name) self.budget_detail.set_amount(amount) if currency is not None: self.budget_detail.set_currency(currency) if wallets is not None: self.budget_detail.set_wallets(wallets) if categories is not None: self.budget_detail.set_categories(categories) if recurrence is not None: self.budget_detail.set_recurrence(recurrence) if start_date is not None: self.budget_detail.set_start_date(start_date) if end_date is not None: self.budget_detail.set_end_date(end_date) def save_budget(self): """Clicks on save budget button""" if self.driver.is_keyboard_shown(): self.driver.hide_keyboard() self.ew.wait_and_tap_element(self.budget_detail.SAVE_BUDGET_BUTTON, 10) self.ew.wait_till_element_is_not_visible( self.budget_detail.SAVE_BUDGET_BUTTON, 10) def open_budget_create_screen(self): """Opens budget create screen, if button is not visible it swipes to it""" self.ew.wait_till_element_is_visible( self.budgets_general.BUDGETS_HEADER, 10) if PLATFORM == "Android": add_button_visible = self.ew.is_element_present( self.budgets_general.ADD_BUDGET_BUTTON) while add_button_visible is False: res = self.rs.get_resolution() self.action.long_press(None, self.rs.all_resolutions[f"{res}"]["x"], self.rs.all_resolutions[f"{res}"]["budget_overview_y_start"]) \ .move_to(None, self.rs.all_resolutions[f"{res}"]["x"], self.rs.all_resolutions[f"{res}"]["budget_overview_y_end"]) \ .release().perform() add_button_visible = self.ew.is_element_present( self.budgets_general.ADD_BUDGET_BUTTON) else: add_button_visible = self.ew.get_attribute( self.budgets_general.ADD_BUDGET_BUTTON, "visible") while add_button_visible == "false": res = self.rs.get_resolution() self.driver.execute_script( "mobile: dragFromToForDuration", { "duration": "0.1", "fromX": self.rs.all_resolutions[f"{res}"]["x"], "fromY": self.rs.all_resolutions[f"{res}"] ["budget_overview_y_start"], "toX": self.rs.all_resolutions[f"{res}"]["x"], "toY": self.rs.all_resolutions[f"{res}"] ["budget_overview_y_end"] }) add_button_visible = self.ew.get_attribute( self.budgets_general.ADD_BUDGET_BUTTON, "visible") self.ew.wait_and_tap_element(self.budgets_general.ADD_BUDGET_BUTTON, 5) self.ew.wait_till_element_is_visible(self.budget_detail.BUDGET_HEADER, 10) def open_budget(self): """Opens existing budget detail screen, if there is no budget created yet, it creates one""" self.budgets_general.go_to_budgets() self.ew.wait_till_element_is_visible( self.budgets_general.BUDGETS_HEADER, 5) if self.ew.is_element_present( self.budgets_general.BUDGET_ITEM) is False: self.create_budget(name="random", amount="random", currency=None, wallets=None, categories=None, recurrence=None, start_date=None, end_date=None) self.save_budget() self.budgets_general.go_to_budgets() self.ew.wait_and_tap_element(self.budgets_general.BUDGET_ITEM, 5) self.ew.wait_and_tap_element( self.budget_overview.BUDGET_SETTINGS_BUTTON, 5) self.ew.wait_till_element_is_visible(self.budget_detail.BUDGET_HEADER, 5) def edit_budget(self, name, amount, currency, wallets, categories, recurrence, start_date, end_date): """ Opens budget edit screen and sets requested attributes of budget :param name: str or None :param amount: str or None :param currency: str or None :param wallets: str or int or None :param categories: str or int or None :param recurrence: str or None :param start_date: str or None :param end_date: str or None """ self.open_budget() if name is not None: if PLATFORM == "Android": self.ew.get_element(self.budget_detail.NAME_INPUT).clear() else: self.ew.get_element( self.budget_detail.SELECTED_NAME_IOS).clear() self.budget_detail.set_name(name) if amount is not None: self.ew.wait_and_tap_element(self.budget_detail.AMOUNT_INPUT, 5) self.ew.wait_till_element_is_visible( self.budget_detail.NUMPAD_CLEAR, 10) for i in range(6): self.ew.tap_element(self.budget_detail.NUMPAD_CLEAR) self.ew.tap_element(self.budget_detail.NUMPAD_BACKDROP) self.budget_detail.set_amount(amount) if currency is not None: self.budget_detail.set_currency(currency) if wallets is not None: self.budget_detail.set_wallets(wallets) if categories is not None: self.budget_detail.set_categories(categories) if recurrence is not None: self.budget_detail.set_recurrence(recurrence) if start_date is not None: self.budget_detail.set_start_date(start_date) if end_date is not None: self.budget_detail.set_end_date(end_date) def delete_budget(self): """Deletes existing budget from budget detail screen""" self.ew.wait_and_tap_element(self.budget_detail.TRASH_ICON, 10) self.ew.wait_and_tap_element(self.budget_detail.DELETE_BUTTON, 10) self.ew.wait_till_element_is_visible( self.budgets_general.BUDGETS_HEADER, 10)
class MarketingDialog: MARKETING_DIALOG = "Marketing Dialog" AGREE_BUTTON = "Agree" DISAGREE_BUTTON = "Don't Agree" ALLOW_BUTTON = 'Allow' def __init__(self, driver): self.driver = driver self.ew = ElementWrapper(self.driver) def agree_with_marketing(self): """Clicks on agree button on marketing dialog""" self.ew.wait_till_element_is_visible(self.MARKETING_DIALOG, 20) self.ew.wait_and_tap_element(self.AGREE_BUTTON, 5) def disagree_with_marketing(self): """Clicks on disagree button on marketing dialog""" self.ew.wait_till_element_is_visible(self.MARKETING_DIALOG, 20) self.ew.wait_and_tap_element(self.DISAGREE_BUTTON, 5) def agree_with_ios_notifications(self): """Clicks on agree button on ios notifications dialog""" if self.ew.is_element_present(self.ALLOW_BUTTON): self.ew.wait_and_tap_element(self.ALLOW_BUTTON, 30)
class CategoryActions: def __init__(self, driver): self.driver = driver self.category_detail = CategoryDetail(self.driver) self.categories_general = CategoriesGeneral(self.driver) self.ew = ElementWrapper(self.driver) self.more_general = MoreGeneral(self.driver) def open_category_create_screen(self): """Opens category create screen""" self.ew.wait_and_tap_element( self.categories_general.ADD_CATEGORY_BUTTON, 10) self.ew.wait_till_element_is_visible( self.category_detail.CATEGORY_HEADER, 10) def open_category(self): """Opens detail of category""" if self.ew.is_element_present( self.categories_general.CATEGORY_ITEM) is False: self.create_category(type_of_category="random", name="random", color="random", image="random") self.save_category() self.ew.wait_and_tap_element(self.categories_general.CATEGORY_ITEM, 10) self.ew.wait_till_element_is_visible( self.category_detail.CATEGORY_HEADER, 10) def create_category(self, type_of_category, name, color, image): """ Sets requested parameters of category inside category detail :param type_of_category: str :param name: str :param color: str :param image: str or int :return: """ self.categories_general.set_type(type_of_category) self.open_category_create_screen() self.category_detail.set_name(name) self.category_detail.set_color(color) self.category_detail.set_image(image) def save_category(self): """Clicks on save category button""" self.ew.wait_and_tap_element(self.category_detail.SAVE_CATEGORY_BUTTON, 10) self.ew.wait_till_element_is_visible( self.more_general.CATEGORIES_HEADER, 10) def confirm_merge(self): """Confirms merge of categories""" self.ew.wait_and_tap_element( self.categories_general.MERGE_CATEGORIES_BUTTON, 10) self.ew.wait_and_tap_element( self.categories_general.CONFIRM_MERGE_BUTTON, 10) self.ew.wait_till_element_is_visible( self.more_general.CATEGORIES_HEADER, 10) def edit_category(self, type_of_category, name, color, image): """ Sets requested attributes inside category detail :param type_of_category: str or None :param name: str or None :param color: str or None :param image: str or int or None """ self.categories_general.set_type(type_of_category) self.open_category() if name is not None: self.category_detail.set_name(name) if color is not None: self.category_detail.set_color(color) if image is not None: self.category_detail.set_image(image) def delete_category(self): """Deletes category""" self.ew.wait_and_tap_element(self.category_detail.TRASH_ICON, 10) self.ew.wait_and_tap_element(self.category_detail.DELETE_BUTTON, 10) self.ew.wait_till_element_is_visible( self.more_general.CATEGORIES_HEADER, 10) def merge_categories(self): """Selects 2 visible categories""" self.ew.wait_and_tap_element( self.categories_general.MERGE_CATEGORIES_BUTTON, 10) all_visible_categories = self.ew.get_attributes( self.categories_general.CATEGORY_INFO, "content-desc") self.ew.tap_element(all_visible_categories[0]) self.ew.tap_element(all_visible_categories[1])
class TransactionTemplateValidator: def __init__(self, driver): self.driver = driver self.action = TouchAction(self.driver) self.ew = ElementWrapper(self.driver) self.period_filter = PeriodFilter(self.driver) self.rs = Resolutions(self.driver) self.timeline_general = TimelineGeneral(self.driver) self.transaction_detail = TransactionDetail(self.driver) self.transaction_validator = TransactionValidator(self.driver) def get_all_attributes(self): """ Getting all attributes of transaction template :return: dict """ all_attributes = { "category": self.transaction_detail.get_category(), "amount": self.transaction_detail.get_amount(), "wallet_amount": self.transaction_detail.get_wallet_amount(), "currency": self.transaction_detail.get_currency(), "wallet": self.transaction_detail.get_wallet("transaction"), "start_date": self.transaction_detail.get_date("start"), "note": self.transaction_detail.get_note(), "labels": self.transaction_detail.get_labels(True), "photo": self.transaction_detail.get_photo(), "recurrence": self.transaction_detail.get_recurrence(), "end_date": self.transaction_detail.get_date("end"), "reminder": self.transaction_detail.get_reminder(), } return all_attributes def is_transaction_template_on_timeline(self, attributes): """ Checking if template is visible inside Scheduled section :param attributes: dict :return: bool """ transaction_locator = f"regular/" \ f"{attributes['category']}/" \ f"{self.transaction_validator.adjust_amounts(attributes['amount'], attributes['wallet_amount'])[0]}/" \ f"{self.transaction_validator.adjust_amounts(attributes['amount'], attributes['wallet_amount'])[1]}/" \ f"{attributes['wallet']}/" \ f"undefined/" \ f"{self.transaction_validator.adjust_note(attributes['note'])}/" \ f"{self.transaction_validator.adjust_labels(attributes['labels'])}/" \ f"{str(attributes['photo']).lower()}/" \ f"{self.adjust_recurrence(attributes['recurrence'])}/" \ f"{self.adjust_end_date(attributes['end_date'])}/" \ f"{self.transaction_validator.adjust_reminder(attributes['reminder'])}" print(f'LOCATOR: {transaction_locator}') self.transaction_validator.prepare_timeline( attributes['start_date'], self.adjust_recurrence(attributes['recurrence'])) android_timeout = time.time() + 60 ios_timeout = time.time() + 5 res = self.rs.get_resolution() is_transaction_present = self.ew.is_element_present( transaction_locator) while is_transaction_present is False: if PLATFORM == "Android": self.transaction_validator.swipe_android(res) is_transaction_present = self.ew.is_element_present( transaction_locator) if time.time() > android_timeout: return False else: is_transaction_present = self.ew.is_element_present( transaction_locator) if time.time() > ios_timeout: return False return True def adjust_recurrence(self, recurrence): """ Adjusting recurrence for template locator :param recurrence: str :return: str """ if recurrence is None or recurrence == "never": return "undefined" else: return recurrence def adjust_end_date(self, end_date): """ Adjusting end date for template locator :param end_date: str :return: str """ if end_date is None: return "undefined" else: return end_date
class WelcomeScreen: WELCOME_SCREEN = "Welcome Screen" SIGN_UP_WITH_EMAIL_BUTTON = "Sign Up With Email" LOGIN_WITH_EMAIL_BUTTON = "Login With Email" SIGN_IN_WITH_GOOGLE_BUTTON = "Sign In With Google" SIGN_IN_WITH_FACEBOOK = "Sign In With Facebook" SIGN_IN_WITH_APPLE = "Sign In With Apple" NOTIFICATIONS_ALERT = '“Spendee” Would Like to Send You Notifications' ALLOW_NOTIFICATIONS_BUTTON = "Allow" ALLOW_FB_LOGIN_BUTTON = 'label == "Continue"' def __init__(self, driver): self.driver = driver self.ew = ElementWrapper(self.driver) def open_sign_up_email_screen(self): """Opens sign up screen for registration via email and password""" self.ew.wait_and_tap_element(self.SIGN_UP_WITH_EMAIL_BUTTON, 30) def open_login_by_email_screen(self): """Opens login screen for login via email and password""" self.ew.wait_and_tap_element(self.LOGIN_WITH_EMAIL_BUTTON, 30) def open_login_by_facebook(self): """Opens sign in screen of Facebook OAuth""" self.ew.wait_and_tap_element(self.SIGN_IN_WITH_FACEBOOK, 30) if PLATFORM == "iOS": self.ew.wait_and_tap_element(self.ALLOW_FB_LOGIN_BUTTON, 15) def open_login_by_google(self): """Opens sign in screen of Google OAuth""" self.ew.wait_and_tap_element(self.SIGN_IN_WITH_GOOGLE_BUTTON, 30) if PLATFORM == "iOS": self.ew.wait_and_tap_element(self.ALLOW_FB_LOGIN_BUTTON, 15) def skip_notifications_alert(self): """Allows notifications on iOS if the dialog is present""" try: self.ew.wait_till_element_is_visible(self.WELCOME_SCREEN, 1) except NoSuchElementException: pass if PLATFORM == "iOS" and self.ew.is_element_present(self.NOTIFICATIONS_ALERT): self.ew.tap_element(self.ALLOW_NOTIFICATIONS_BUTTON)
def __init__(self, driver): self.driver = driver self.action = TouchAction(self.driver) self.ew = ElementWrapper(self.driver) self.rs = Resolutions(self.driver)
def __init__(self, driver): self.driver = driver self.ew = ElementWrapper(self.driver) self.export_general = ExportGeneral(self.driver)
def __init__(self, driver): self.driver = driver self.action = TouchAction(self.driver) self.ew = ElementWrapper(self.driver) self.rs = Resolutions(self.driver) self.transaction_detail = TransactionDetail(self.driver)
def __init__(self, driver): self.driver = driver self.category_detail = CategoryDetail(self.driver) self.categories_general = CategoriesGeneral(self.driver) self.ew = ElementWrapper(self.driver) self.more_general = MoreGeneral(self.driver)
class AuthenticationActions: def __init__(self, driver): self.driver = driver self.ew = ElementWrapper(self.driver) self.email_password = EmailPassword(self.driver) self.facebook = Facebook(self.driver) self.google = Google(self.driver) self.marketing_dialog = MarketingDialog(self.driver) self.more_general = MoreGeneral(self.driver) self.timeline_general = TimelineGeneral(self.driver) self.user_profile = UserProfile(self.driver) self.welcome_screen = WelcomeScreen(self.driver) def register_by_email(self, email, password): """ Goes through registration process by email and password :param email: str :param password: str """ self.welcome_screen.open_sign_up_email_screen() self.email_password.set_email(email) self.email_password.set_password(password) self.ew.tap_element(self.email_password.SIGN_UP_BUTTON) time.sleep(0.5) if PLATFORM == "iOS": self.marketing_dialog.agree_with_ios_notifications() def login_by_facebook(self, email, password): """ Goes through sign in process by Facebook :param email: str :param password: str """ self.welcome_screen.open_login_by_facebook() self.ew.wait_till_element_is_visible(self.facebook.FACEBOOK_HEADER, 30) if self.ew.is_element_present(self.facebook.COOKIES_ACCEPT_BUTTON): self.ew.tap_element(self.facebook.COOKIES_ACCEPT_BUTTON) self.ew.get_element(self.facebook.EMAIL_TEXT_BOX).send_keys(email) self.ew.get_element( self.facebook.PASSWORD_TEXT_BOX).send_keys(password) self.ew.wait_and_tap_element(self.facebook.LOGIN_BUTTON, 10) self.ew.wait_and_tap_element(self.facebook.CONTINUE_BUTTON, 20) if PLATFORM == "iOS": self.marketing_dialog.agree_with_ios_notifications() def login_by_email(self, email, password): """ Goes through login process by email and password :param email: str :param password: str """ self.welcome_screen.open_login_by_email_screen() self.email_password.set_email(email) self.email_password.set_password(password) self.ew.tap_element(self.email_password.LOGIN_BUTTON) if PLATFORM == "iOS": self.marketing_dialog.agree_with_ios_notifications() def login_by_google(self): """Goes through sign in process by Google, when user was previously logged on device""" self.welcome_screen.open_login_by_google() self.ew.wait_and_tap_element(self.google.EMAIL_TO_SELECT, 20) def logout(self): """Logouts user from the application""" self.more_general.go_to_more_section() self.ew.swipe_if_element_not_present(self.more_general.LOGOUT_BUTTON) self.ew.tap_element(self.more_general.LOGOUT_BUTTON)