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 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 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 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 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 WalletDetail: # OTHER WALLET_HEADER = "Wallet Header" SAVE_WALLET_BUTTON = "Save Wallet 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 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 Subtraction" } NUMPAD_BACKDROP = "Numpad Backdrop" NUMPAD_CLEAR = "Numpad Clear" if PLATFORM == "Android": AMOUNT_INPUT = "Amount Input" else: AMOUNT_INPUT = '**/XCUIElementTypeOther[`label == "Amount Input"`][2]' SELECTED_AMOUNT = "Currency Input" # 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"' # CATEGORIES CATEGORIES_HEADER = "Categories Header" BACK_BUTTON = "Back Button" EYE_ICON = "Eye Icon" if PLATFORM == "Android": CATEGORIES = "Categories" EYE_ICON = "Eye Icon" 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: CATEGORIES = 'label == "Categories"' EYE_ICON = 'label == "Eye Icon"' # SHARING SHARE_WALLET_BUTTON = "Share Wallet Button" if PLATFORM == "Android": DENY_BUTTON = 'com.android.packageinstaller:id/permission_deny_button' else: DENY_BUTTON = 'Don’t Allow' def __init__(self, driver): self.driver = driver self.ew = ElementWrapper(self.driver) def set_name(self, name): """ Inserting 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) if self.driver.is_keyboard_shown(): self.driver.hide_keyboard() vr.validate_input_against_output(name, self.get_name()) def get_name(self): """ Getting name 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): """ Inserting amount into balance input :param amount: str """ if amount == "random": amount = str(random.randint(-99, 99)) elif amount == "random_positive": amount = str(random.randint(1, 99)) elif amount == "random_negative": amount = str(random.randint(-99, -1)) 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): """ Getting amount from balance 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): """ Selecting currency of wallet :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): """ Getting selected currency of wallet :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_categories(self, categories): """ Selecting visible categories of wallet :param categories: "random" or int """ if PLATFORM == "Android": v_input = self.get_categories() self.ew.wait_and_tap_element(self.CATEGORIES, 5) self.ew.wait_till_element_is_visible(self.CATEGORIES_HEADER, 5) if categories == "random": categories = random.randint(1, 5) visible_categories = self.ew.get_elements(self.EYE_ICON) x = 0 for i in visible_categories: x = x + 1 if x <= categories: i.click() self.ew.wait_and_tap_element(self.BACK_BUTTON, 5) vr.validate_input_against_output( int(v_input) - categories, int(self.get_categories())) def get_categories(self): """ Getting number of visible categories of wallet :return: str """ self.ew.wait_till_element_is_visible(self.CATEGORIES, 5) time.sleep(1) 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 invite_user(self): """Opening invitation screen""" self.ew.wait_and_tap_element(self.SHARE_WALLET_BUTTON, 15)
class TransactionDetail: # OTHER BACK_BUTTON = "Back Button" if PLATFORM == "Android": TRANSACTION_HEADER_TITLE = "Transaction Header Title" else: TRANSACTION_HEADER_TITLE = '**/XCUIElementTypeStaticText[`label == "Transaction Header Title"`]' SAVE_TRANSACTION_BUTTON = "Save Transaction Button" TRASH_ICON = "Trash Icon" DELETE_BUTTON = "Delete" # 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" # TYPE AND CATEGORY CATEGORY_ICON = "Category Icon" EXPENSES_PICKER = "Expenses Picker" INCOME_PICKER = "Income Picker" TRANSACTION_PICKER = "Transaction Picker" TRANSFER_PICKER = "Transfer Picker" if PLATFORM == "Android": SELECTED_TYPE = "Selected Type" else: SELECTED_TYPE = '**/XCUIElementTypeStaticText[`label == "Selected Type"`]' GEAR_ICON = "Gear Icon" CONFIRM_CATEGORY_ICON = "Confirm Category Icon" # AMOUNT if PLATFORM == "Android": AMOUNT_INPUT = "//android.view.ViewGroup[@content-desc='Amount Input']/android.view.ViewGroup/android.widget.TextView" WALLET_AMOUNT = "//android.view.ViewGroup[@content-desc='Wallet Price']/android.widget.TextView" else: AMOUNT_INPUT = 'label == "Amount Input"' WALLET_AMOUNT = "//XCUIElementTypeOther[@name='Wallet Price']/XCUIElementTypeStaticText" # CURRENCY CONFIRM_BUTTON = "Confirm Button" if PLATFORM == "Android": CURRENCY = "Currency" else: CURRENCY = "(//XCUIElementTypeOther[@name='Currency'])[1]/XCUIElementTypeOther" SELECTED_CURRENCY_ANDROID = "//android.view.ViewGroup[@content-desc='Currency']/android.widget.TextView" # WALLET if PLATFORM == "Android": WALLET = "Wallet" OUTGOING_WALLET = "Outgoing Wallet" INCOMING_WALLET = "Incoming Wallet" WALLET_ITEM = '//android.view.ViewGroup[@content-desc="Select Wallet Picker"]/android.widget.ScrollView/' \ 'android.view.ViewGroup/android.widget.ScrollView/android.view.ViewGroup/android.view.ViewGroup' else: WALLET = 'label == "Wallet"' OUTGOING_WALLET = 'label == "Outgoing Wallet"' INCOMING_WALLET = 'label == "Incoming Wallet"' WALLET_ITEM = "Wallet Item" WALLET_PICKER = "Select Wallet Picker" SELECTED_WALLET_ANDROID = "//android.view.ViewGroup[@content-desc='Wallet']//android.widget.TextView[2]" SELECTED_OUTGOING_WALLET_ANDROID = "//android.view.ViewGroup[@content-desc='Outgoing Wallet']//android.widget.TextView[2]" SELECTED_INCOMING_WALLET_ANDROID = "//android.view.ViewGroup[@content-desc='Incoming Wallet']//android.widget.TextView[2]" # START DATE CALENDAR_PICKER = "Select date Picker" SELECTED_START_DATE_ANDROID = "//android.view.ViewGroup[@content-desc='Start Date']/android.view.ViewGroup/android.widget.TextView" SELECTED_START_DATE_ANDROID_2 = "//android.view.ViewGroup[@content-desc='Start Date']/android.widget.TextView" SELECTED_END_DATE_ANDROID = "//android.view.ViewGroup[@content-desc='End Date']/android.view.ViewGroup/android.widget.TextView[2]" SELECTED_END_DATE_ANDROID_2 = "//android.view.ViewGroup[@content-desc='End Date']/android.widget.TextView[2]" SELECTED_START_DATE_ANDROID_BUDGET = '//android.view.ViewGroup[@content-desc="Start Date"]/android.view.ViewGroup/android.widget.TextView[2]' SELECTED_START_DATE_ANDROID_BUDGET_2 = '//android.view.ViewGroup[@content-desc="Start Date"]/android.widget.TextView[2]' SELECTED_END_DATE_ANDROID_BUDGET = '//android.view.ViewGroup[@content-desc="End Date"]/android.view.ViewGroup/android.widget.TextView[2]' SELECTED_END_DATE_ANDROID_BUDGET_2 = '//android.view.ViewGroup[@content-desc="End Date"]/android.widget.TextView[2]' if PLATFORM == "Android": START_DATE = "Start Date" ACTUAL_MONTH_YEAR = "//android.widget.SeekBar/android.widget.TextView" else: START_DATE = 'label == "Start Date"' ACTUAL_MONTH_YEAR = "(//XCUIElementTypeOther[@name='Select date Picker']//XCUIElementTypeOther[contains(@name,'undefined')])[2]" # NOTE if PLATFORM == "Android": NOTE = "Note" EXISTING_NOTE = "Note" else: NOTE = "//XCUIElementTypeTextView[@name='Note Write a note']" EXISTING_NOTE = '**/XCUIElementTypeTextView[`label == "Note"`]' SELECTED_NOTE_IOS = "Note" NOTE_ELEMENT = "Note Element" # LABELS LABELS = "Labels" LABEL_ITEM = "Label Item" if PLATFORM == "Android": LABEL_INPUT = "//android.widget.EditText" else: LABEL_INPUT = "//XCUIElementTypeTextField" NON_EXISTING_LABEL = "Non Existing Label" VISIBLE_LABELS_ANDROID = "//android.view.ViewGroup[@content-desc='Label Item']/android.widget.TextView" VISIBLE_LABELS_IOS = "//XCUIElementTypeOther[@name='Label Item']/XCUIElementTypeOther" SELECTED_LABELS_ANDROID = "//android.view.ViewGroup[@content-desc='Check Mark']/android.view.ViewGroup/ancestor::*[1]/following-sibling::*[1]" PREMIUM_LABEL_ALERT = "Premium Label Alert" NOT_NOW_BUTTON = "Now now" # PHOTO PHOTO = "Photo" SELECTED_PHOTO = "Selected Photo" if PLATFORM == "Android": CHOOSE_PHOTO = "//android.widget.TextView[2]" PHOTO_FOLDER = "//android.widget.RelativeLayout" PHOTO_ITEM = "(//android.support.v7.widget.RecyclerView/android.view.ViewGroup)[1]" else: CHOOSE_PHOTO = "Choose from Library…" PHOTO_FOLDER = "All Photos" PHOTO_ITEM = "(//XCUIElementTypeImage)[1]" ALLOW_PHOTO_ACCESS_ANDROID = "com.android.packageinstaller:id/permission_allow_button" # RECURRENCE if PLATFORM == "Android": RECURRENCE = "Recurrence" else: RECURRENCE = 'label == "Recurrence"' RECURRENCE_PICKER = "Recurrence Picker" SELECTED_RECURRENCE_ANDROID = "//android.view.ViewGroup[@content-desc='Recurrence']/android.view.ViewGroup/android.widget.TextView[2]" SELECTED_RECURRENCE_ANDROID_EDIT = '//android.view.ViewGroup[@content-desc="Recurrence"]/android.widget.TextView[2]' # END DATE if PLATFORM == "Android": END_DATE = "End Date" else: END_DATE = 'label == "End Date"' # REMINDER if PLATFORM == "Android": REMINDER = "Reminder" else: REMINDER = 'label == "Reminder"' REMINDER_PICKER = "Reminder Picker" SELECTED_REMINDER_ANDROID = "//android.view.ViewGroup[@content-desc='Reminder']/android.view.ViewGroup/android.widget.TextView[2]" def __init__(self, driver): self.driver = driver self.action = TouchAction(self.driver) self.ew = ElementWrapper(self.driver) self.rs = Resolutions(self.driver) def set_type_of_transaction(self, transaction_type): """ Selects type of transaction :param transaction_type: str """ if transaction_type == "random": transaction_type = random.choice( [self.EXPENSES_PICKER, self.INCOME_PICKER]) elif transaction_type == "opposite": actual_type = self.get_type_of_transaction() if actual_type == "Expenses": transaction_type = self.INCOME_PICKER else: transaction_type = self.EXPENSES_PICKER elif transaction_type == "expenses": transaction_type = self.EXPENSES_PICKER elif transaction_type == "income": transaction_type = self.INCOME_PICKER if transaction_type == self.EXPENSES_PICKER: v_input = "Expenses" else: v_input = "Income" self.ew.wait_and_tap_element(transaction_type, 5) if PLATFORM == "Android": time.sleep(0.5) vr.validate_input_against_output(v_input, self.get_type_of_transaction()) def get_type_of_transaction(self): """ Gets type of transaction :return: str """ self.ew.wait_till_element_is_visible(self.SELECTED_TYPE, 5) if PLATFORM == "Android": return self.ew.get_text_of_element(self.SELECTED_TYPE) else: return self.ew.get_attribute(self.SELECTED_TYPE, "name") def set_type_to_transfer(self): """Will select type as transfer""" self.ew.wait_and_tap_element(self.TRANSFER_PICKER, 5) self.ew.wait_till_element_is_not_visible(self.TRANSFER_PICKER, 5) if self.ew.is_element_present(self.NUMPAD_BACKDROP): pass else: vr.validate_input_against_output("Transfer", self.get_category()) def open_type_picker(self): """Opens type picker""" self.ew.wait_and_tap_element(self.CATEGORY_ICON, 10) def set_category(self, category): """ Selects category from category picker :param category: str """ self.ew.wait_till_element_is_visible(self.TRANSACTION_PICKER, 5) if category == "random": category_visible = False timeout = time.time() + 15 while category_visible is False: category = random.choice(vs.default_set_of_categories) category_visible = self.ew.is_element_present( f"Category {category}") if time.time() > timeout: break self.ew.tap_element(f"Category {category}") self.ew.wait_till_element_is_not_visible(self.TRANSACTION_PICKER, 5) if self.ew.is_element_present(self.NUMPAD_BACKDROP): pass else: vr.validate_input_against_output(category, self.get_category()) def get_category(self): """ Gets selected category :return: str """ self.ew.wait_till_element_is_visible(self.TRANSACTION_HEADER_TITLE, 5) if PLATFORM == "Android": category = self.ew.get_text_of_element( self.TRANSACTION_HEADER_TITLE).split(" ")[1:] else: category = self.ew.get_attribute(self.TRANSACTION_HEADER_TITLE, "name").split(" ")[1:] return ' '.join(category) 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_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) v_output = self.get_amount() if v_output.startswith("-"): v_output = v_output[1:] vr.validate_input_against_output(''.join(str(i) for i in amount_list), v_output) def get_amount(self): """ Gets amount from amount picker :return: str """ self.ew.wait_till_element_is_visible(self.AMOUNT_INPUT, 5) if PLATFORM == "Android": return self.ew.get_text_of_element(self.AMOUNT_INPUT) else: amount = self.ew.get_attribute(self.AMOUNT_INPUT, "name") if amount.startswith("+"): amount = amount[1:] return amount def get_wallet_amount(self): """ Gets wallet's amount when category has different currency :return: str """ self.ew.wait_till_element_is_visible(self.AMOUNT_INPUT, 5) try: if PLATFORM == "Android": return self.ew.get_text_of_element(self.WALLET_AMOUNT) else: return self.ew.get_attribute(self.WALLET_AMOUNT, "name") except NoSuchElementException: return None def set_currency(self, currency): """ Selects currency :param currency: str """ if currency == "random": currency = random.choice(vs.accessible_currencies) self.ew.wait_and_tap_element(self.CURRENCY, 5) self.ew.wait_and_tap_element(f"Currency {currency}", 10) self.set_exchange_rate() vr.validate_input_against_output(currency, self.get_currency()) def get_currency(self): """ Gets selected currency :return: str """ self.ew.wait_till_element_is_visible(self.CURRENCY, 5) if PLATFORM == "Android": return self.ew.get_attribute(self.SELECTED_CURRENCY_ANDROID, "content-desc") else: return self.ew.get_attribute(self.CURRENCY, "name") def set_exchange_rate(self): self.ew.wait_and_tap_element(self.CONFIRM_BUTTON, 10) def set_wallet(self, wallet, type_of_wallet): """ Selects requested wallet from requested wallet picker :param wallet: str :param type_of_wallet: str """ selected_wallet = self.get_wallet(type_of_wallet) if type_of_wallet == "transaction": self.ew.wait_and_tap_element(self.WALLET, 5) elif type_of_wallet == "transfer_outgoing": self.ew.wait_and_tap_element(self.OUTGOING_WALLET, 5) elif type_of_wallet == "transfer_incoming": self.ew.wait_and_tap_element(self.INCOMING_WALLET, 5) self.ew.wait_till_element_is_visible(self.WALLET_PICKER, 5) wallets_in_picker = self.get_wallets_in_picker() if wallet == "random": wallet = random.choice(wallets_in_picker) if PLATFORM == "Android": self.ew.tap_element(wallet) else: self.ew.tap_element(f'label == "{wallet}"') elif wallet == "different": wallets_in_picker.remove(selected_wallet) wallet = random.choice(wallets_in_picker) if PLATFORM == "Android": self.ew.tap_element(wallet) else: self.ew.tap_element(f'label == "{wallet}"') elif wallet == "oos": for i in wallets_in_picker: if i.startswith('Out of Spendee'): postfix_oos = i.split('-')[1] wallet = f"Out of Spendee-{postfix_oos}" if PLATFORM == "Android": self.ew.tap_element(wallet) else: self.ew.tap_element(f'label == "{wallet}"') elif wallet == "not_oos": if self.ew.is_element_present("Out of Spendee-false"): wallets_in_picker.remove("Out of Spendee-false") elif self.ew.is_element_present("Out of Spendee-true"): wallets_in_picker.remove("Out of Spendee-true") wallet = random.choice(wallets_in_picker) if PLATFORM == "Android": self.ew.tap_element(wallet) else: self.ew.tap_element(f'label == "{wallet}"') else: if PLATFORM == "Android": self.ew.tap_element(wallet) else: self.ew.tap_element(f'label == "{wallet}"') self.ew.wait_till_element_is_not_visible(self.WALLET_PICKER, 5) if self.ew.is_element_present(self.CONFIRM_BUTTON): self.set_exchange_rate() v_input = wallet.split('-')[0] vr.validate_input_against_output(v_input, self.get_wallet(type_of_wallet)) def get_wallet(self, type_of_wallet): """ Gets wallet name from requested wallet picker :param type_of_wallet: str :return: str """ if PLATFORM == "Android": if type_of_wallet == "transaction": self.ew.wait_till_element_is_visible( self.SELECTED_WALLET_ANDROID, 5) return self.ew.get_text_of_element( self.SELECTED_WALLET_ANDROID) elif type_of_wallet == "transfer_outgoing": self.ew.wait_till_element_is_visible( self.SELECTED_OUTGOING_WALLET_ANDROID, 5) return self.ew.get_text_of_element( self.SELECTED_OUTGOING_WALLET_ANDROID) elif type_of_wallet == "transfer_incoming": self.ew.wait_till_element_is_visible( self.SELECTED_INCOMING_WALLET_ANDROID, 5) return self.ew.get_text_of_element( self.SELECTED_INCOMING_WALLET_ANDROID) else: if type_of_wallet == "transaction": self.ew.wait_till_element_is_visible(self.WALLET, 5) return self.ew.get_attribute(self.WALLET, "name") elif type_of_wallet == "transfer_outgoing": self.ew.wait_till_element_is_visible(self.OUTGOING_WALLET, 5) return self.ew.get_attribute(self.OUTGOING_WALLET, "name") elif type_of_wallet == "transfer_incoming": self.ew.wait_till_element_is_visible(self.INCOMING_WALLET, 5) return self.ew.get_attribute(self.INCOMING_WALLET, "name") def get_wallets_in_picker(self): """ Gets wallets names visible inside picker :return: list of str """ if PLATFORM == "Android": return self.ew.get_attributes(self.WALLET_ITEM, "content-desc") else: return self.ew.get_attributes(self.WALLET_ITEM, "label") def set_start_date(self, start_date): """ Sets start date :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 == "past": start_date = str(datetime.date.today() - datetime.timedelta(days=random.randint(1, 30))) elif start_date == "future": start_date = str(datetime.date.today() + datetime.timedelta(days=random.randint(1, 30))) 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.set_calendar_month_year(start_date) self.set_calendar_day(start_date) vr.validate_input_against_output(start_date, self.get_date("start")) def set_calendar_month_year(self, date): """ Swipes to requested month and year inside date picker :param date: str """ year, month, day = (int(x) for x in date.split('-')) if PLATFORM == "Android": month_in_app = vs.calendar_months[self.ew.get_text_of_element( self.ACTUAL_MONTH_YEAR).split(" ")[0]] year_in_app = int( self.ew.get_text_of_element( self.ACTUAL_MONTH_YEAR).split(" ")[1]) else: month_in_app = vs.calendar_months[self.ew.get_attribute( self.ACTUAL_MONTH_YEAR, "label").split(" ")[0]] year_in_app = int( self.ew.get_attribute(self.ACTUAL_MONTH_YEAR, "label").split(" ")[1]) direction = None if (year > year_in_app) or (year == year_in_app and month > month_in_app): direction = "up" elif (year < year_in_app) or (year == year_in_app and month < month_in_app): direction = "down" iterations = abs((year - year_in_app) * 12 + (month - month_in_app)) res = self.rs.get_resolution() if PLATFORM == "Android": if direction == "up": for i in range(iterations): self.action.long_press(None, self.rs.all_resolutions[f"{res}"]["x"], self.rs.all_resolutions[f"{res}"]["calendar_picker_up_y_start"]) \ .move_to(None, self.rs.all_resolutions[f"{res}"]["x"], self.rs.all_resolutions[f"{res}"]["calendar_picker_up_y_end"]) \ .release().perform() elif direction == "down": for i in range(iterations): for d in range(2): self.action.long_press(None, self.rs.all_resolutions[f"{res}"]["x"], self.rs.all_resolutions[f"{res}"]["calendar_picker_down_y_start"]) \ .move_to(None, self.rs.all_resolutions[f"{res}"]["x"], self.rs.all_resolutions[f"{res}"]["calendar_picker_down_y_end"]) \ .release().perform() elif PLATFORM == "iOS": if direction == "up": for i in range(iterations): self.driver.execute_script( "mobile: dragFromToForDuration", { "duration": "0.1", "fromX": self.rs.all_resolutions[f"{res}"]["x"], "fromY": self.rs.all_resolutions[f"{res}"] ["calendar_picker_up_y_start"], "toX": self.rs.all_resolutions[f"{res}"]["x"], "toY": self.rs.all_resolutions[f"{res}"] ["calendar_picker_up_y_end"] }) elif direction == "down": for i in range(iterations): self.driver.execute_script( "mobile: dragFromToForDuration", { "duration": "0.1", "fromX": self.rs.all_resolutions[f"{res}"]["x"], "fromY": self.rs.all_resolutions[f"{res}"] ["calendar_picker_down_y_start"], "toX": self.rs.all_resolutions[f"{res}"]["x"], "toY": self.rs.all_resolutions[f"{res}"] ["calendar_picker_down_y_end"] }) def set_calendar_day(self, date): """ Selects requested day inside date picker :param date: str """ if PLATFORM == "Android": year, month, day = (int(x) for x in date.split('-')) if date == str(datetime.date.today()): self.ew.tap_element( f"today {datetime.date(year, month, day).strftime('%A')} {datetime.date(year, month, day).strftime('%B')} {day} selected You have no entries for this day " ) else: self.ew.tap_element( f" {datetime.date(year, month, day).strftime('%A')} {datetime.date(year, month, day).strftime('%B')} {day} " ) elif PLATFORM == "iOS": self.ew.wait_and_tap_element( f"native.calendar.SELECT_DATE_SLOT-{date}", 10) def get_date(self, type_of_date): """ Gets selected date :param type_of_date: str """ is_transaction = self.ew.is_element_present( self.TRANSACTION_HEADER_TITLE) if type_of_date == "start": date_ios = self.START_DATE if is_transaction: date_android = self.SELECTED_START_DATE_ANDROID else: date_android = self.SELECTED_START_DATE_ANDROID_BUDGET else: date_ios = self.END_DATE if is_transaction: date_android = self.SELECTED_END_DATE_ANDROID else: date_android = self.SELECTED_END_DATE_ANDROID_BUDGET try: if PLATFORM == "Android": try: self.ew.wait_till_element_is_visible(date_android, 5) except NoSuchElementException: if type_of_date == "start": if is_transaction: date_android = self.SELECTED_START_DATE_ANDROID_2 else: date_android = self.SELECTED_START_DATE_ANDROID_BUDGET_2 else: if is_transaction: date_android = self.SELECTED_END_DATE_ANDROID_2 else: date_android = self.SELECTED_END_DATE_ANDROID_BUDGET_2 date_in_app = self.ew.get_text_of_element(date_android) else: self.ew.wait_till_element_is_visible(date_ios, 5) date_in_app = self.ew.get_attribute(date_ios, "name") except (NoSuchElementException, AttributeError): return None if date_in_app == "Today" or date_in_app == "Yesterday?": date = str(datetime.date.today()) elif date_in_app == "Yesterday": date = str(datetime.date.today() - datetime.timedelta(days=1)) elif date_in_app == "Tomorrow": date = str(datetime.date.today() + datetime.timedelta(days=1)) elif date_in_app is None or date_in_app == "Never": return None else: try: month, day, year = (str(x) for x in date_in_app.split(' ')) day = day.replace(",", "") except ValueError: month, day = (str(x) for x in date_in_app.split(' ')) year = str(datetime.date.today().year) month = str(datetime.datetime.strptime(month, "%B").month).zfill(2) date = f"{year}-{month}-{day.zfill(2)}" return date def set_note(self, note): """ Insert note into note input :param note: str """ if note == "random": note = ''.join([ random.choice(string.ascii_lowercase + string.digits) for n in range(0, 8) ]) self.ew.wait_till_element_is_visible(self.NOTE_ELEMENT, 5) self.ew.get_element(self.NOTE).send_keys(note) if self.driver.is_keyboard_shown(): self.ew.tap_element(self.NOTE_ELEMENT) vr.validate_input_against_output(note, self.get_note()) def get_note(self): """ Gets note from note picker :return: str """ try: if PLATFORM == "Android": note = self.ew.get_text_of_element(self.NOTE) if note == "Write a note": note = "" return note else: return self.ew.get_text_of_elements(self.SELECTED_NOTE_IOS)[2] except IndexError: return None def set_label(self, label): """ Selects label from visible labels, if there is no requested label, it creates one :param label: str """ self.ew.wait_till_element_is_visible(self.LABELS, 5) if label == "random": if self.ew.is_element_present(self.LABEL_ITEM): labels = self.get_labels(False) label = random.choice(labels) if PLATFORM == "Android": self.ew.tap_element(label) time.sleep(0.5) else: i = labels.index(label) self.action.tap(self.ew.get_elements( self.LABEL_ITEM)[i]).perform() vr.validate_input_against_more_outputs(label, self.get_labels(True)) else: self.create_label(label) else: if PLATFORM == "Android": if self.ew.is_element_present(label): self.ew.tap_element(label) time.sleep(0.5) vr.validate_input_against_more_outputs( label, self.get_labels(True)) else: self.create_label(label) else: labels = self.get_labels(False) if label in labels: i = labels.index(label) self.action.tap(self.ew.get_elements( self.LABEL_ITEM)[i]).perform() vr.validate_input_against_more_outputs( label, self.get_labels(True)) else: self.create_label(label) def fast_select_labels(self, number): """ Selects more labels on transaction detail screen :param number: int """ self.ew.wait_till_element_is_visible(self.LABELS, 5) if self.ew.is_element_present(self.LABEL_ITEM): labels = self.get_labels(False) x = 0 for i in labels: x = x + 1 if x <= number: if PLATFORM == "Android": self.ew.tap_element(i) time.sleep(0.5) else: label = labels.index(i) self.action.tap( self.ew.get_elements( self.LABEL_ITEM)[label]).perform() def create_label(self, name): """ Creates labels on label picker :param name: str :return: """ if name == "random": name = ''.join([ random.choice(string.ascii_lowercase + string.digits) for n in range(0, 8) ]) self.ew.tap_element(self.LABELS) self.ew.wait_and_tap_element(self.LABEL_INPUT, 5) self.ew.get_element(self.LABEL_INPUT).send_keys(name) self.ew.wait_and_tap_element(self.NON_EXISTING_LABEL, 5) self.ew.tap_element(self.BACK_BUTTON) vr.validate_input_against_more_outputs(name, self.get_labels(True)) def get_labels(self, only_selected): """ Returns all visible or only selected labels :param only_selected: bool :return: list of str """ self.ew.wait_till_element_is_visible(self.LABELS, 5) if PLATFORM == "Android": if only_selected: labels = self.ew.get_text_of_elements( self.SELECTED_LABELS_ANDROID) else: labels = self.ew.get_text_of_elements( self.VISIBLE_LABELS_ANDROID) else: attributes = self.ew.get_attributes(self.VISIBLE_LABELS_IOS, "name") labels = [] for i in attributes: if only_selected: if i.endswith("false") is False: labels.append(i.split("-")[0]) else: labels.append(i.split("-")[0]) return labels def set_photo(self): """Selects photo""" self.ew.wait_and_tap_element(self.PHOTO, 5) self.ew.wait_and_tap_element(self.CHOOSE_PHOTO, 5) if self.ew.is_element_present(self.ALLOW_PHOTO_ACCESS_ANDROID): self.ew.tap_element(self.ALLOW_PHOTO_ACCESS_ANDROID) if PLATFORM == "Android": self.ew.wait_and_tap_element(self.PHOTO_FOLDER, 5) self.ew.wait_and_tap_element(self.PHOTO_ITEM, 5) vr.validate_input_against_output(True, self.get_photo()) def get_photo(self): """ Returns true if photo is selected :return: bool """ try: self.ew.wait_till_element_is_visible(self.PHOTO, 5) self.ew.wait_till_element_is_visible(self.SELECTED_PHOTO, 3) except: NoSuchElementException() return self.ew.is_element_present(self.SELECTED_PHOTO) def set_recurrence(self, recurrence): """ Swipes to and selects requested recurrence :param recurrence: string """ if recurrence == "random": recurrence = random.choice(vs.recurrences) self.ew.wait_and_tap_element(self.RECURRENCE, 5) self.ew.wait_till_element_is_visible(self.RECURRENCE_PICKER, 5) 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 """ try: self.ew.wait_till_element_is_visible(self.RECURRENCE, 5) if PLATFORM == "Android": try: recurrence = self.ew.get_text_of_element( self.SELECTED_RECURRENCE_ANDROID).lower() except AttributeError: recurrence = self.ew.get_text_of_element( self.SELECTED_RECURRENCE_ANDROID_EDIT).lower() else: recurrence = self.ew.get_attribute(self.RECURRENCE, "name").lower() if recurrence != "never" and PLATFORM == "Android": recurrences_in_app = [ "every day", "every 2 days", "every work day", "every week", "every 2 weeks", "every 4 weeks", "every month", "every 2 months", "every 3 months", "every 6 months", "every year" ] recurrence = vs.recurrences[recurrences_in_app.index( recurrence)] return recurrence except (AttributeError, NoSuchElementException): return None def set_end_date(self, end_date): """ Selects end date from date picker :param end_date: str """ start_date = self.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.set_calendar_month_year(end_date) self.set_calendar_day(end_date) vr.validate_input_against_output(end_date, self.get_date("end")) def set_reminder(self, reminder): """ Swipes to and selects requested reminder :param reminder: str """ if reminder == "random": reminder = random.choice(vs.reminders) self.ew.wait_and_tap_element(self.REMINDER, 5) self.ew.wait_till_element_is_visible(self.REMINDER_PICKER, 5) res = self.rs.get_resolution() if PLATFORM == "Android": item_visible = self.ew.is_element_present(reminder) 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(reminder) self.ew.wait_and_tap_element(reminder, 5) else: item_visible = self.ew.get_attribute(reminder, "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(reminder, "visible") self.driver.execute_script("mobile: tap", { "x": 100, "y": 50, "element": self.ew.get_element(reminder) }) vr.validate_input_against_output(reminder, self.get_reminder()) def get_reminder(self): """ Gets selected reminder :return: str """ try: self.ew.wait_till_element_is_visible(self.REMINDER, 5) if PLATFORM == "Android": reminder = self.ew.get_text_of_element( self.SELECTED_REMINDER_ANDROID) else: reminder = self.ew.get_attribute(self.REMINDER, "name") if reminder != "Never": reminders_in_app = [ "On a transaction date", "1 day before", "2 days before", "3 days before", "4 days before", "5 days before", "6 days before", "7 days before" ] reminder = vs.reminders[reminders_in_app.index(reminder)] return reminder except (ValueError, NoSuchElementException): return None