Ejemplo n.º 1
0
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)
Ejemplo n.º 2
0
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)
Ejemplo n.º 3
0
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
Ejemplo n.º 4
0
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)
Ejemplo n.º 5
0
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)
Ejemplo n.º 6
0
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])
Ejemplo n.º 7
0
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
Ejemplo n.º 8
0
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)
Ejemplo n.º 9
0
class TransactionActions:
    EXISTING_TRANSACTION = "Existing Item: regular-undefined"
    EXISTING_TRANSACTION_TEMPLATES = [
        "Existing Item: regular-every day",
        "Existing Item: regular-every 2 days",
        "Existing Item: regular-every working day",
        "Existing Item: regular-every week",
        "Existing Item: regular-every 2 weeks",
        "Existing Item: regular-every 4 weeks",
        "Existing Item: regular-every month",
        "Existing Item: regular-every 2 months",
        "Existing Item: regular-every 3 months",
        "Existing Item: regular-every 6 months",
        "Existing Item: regular-every year"
    ]

    def __init__(self, driver):
        self.driver = driver
        self.ew = ElementWrapper(self.driver)
        self.timeline_general = TimelineGeneral(self.driver)
        self.transaction_detail = TransactionDetail(self.driver)
        self.transfer_destination_modal = TransferDestinationModal(self.driver)

    def create_transaction(self, transaction_type, category, amount, currency,
                           wallet, start_date, note, label, photo, recurrence,
                           end_date, reminder):
        """
        Opens create transaction screen and sets requested attributes
        :param transaction_type: str or None
        :param category: str or None
        :param amount: str or None
        :param currency: str or None
        :param wallet: str or None
        :param start_date: str or None
        :param note: str or None
        :param label: str or None
        :param photo: bool
        :param recurrence: str or None
        :param end_date: str or None
        :param reminder: str or None
        """
        self.timeline_general.open_transaction_create_screen()
        if transaction_type is not None:
            self.transaction_detail.set_type_of_transaction(transaction_type)
        self.transaction_detail.set_category(category)
        self.transaction_detail.set_amount(amount)
        if currency is not None:
            self.transaction_detail.set_currency(currency)
        if wallet is not None:
            self.transaction_detail.set_wallet(wallet, "transaction")
        if start_date is not None:
            self.transaction_detail.set_start_date(start_date)
        if note is not None:
            self.transaction_detail.set_note(note)
        if label is not None:
            self.transaction_detail.set_label(label)
        if photo is not None:
            self.transaction_detail.set_photo()
        if recurrence is not None:
            self.ew.wait_till_element_is_visible(
                self.transaction_detail.SAVE_TRANSACTION_BUTTON, 5)
            self.ew.swipe_if_element_not_present(
                self.transaction_detail.RECURRENCE)
            self.transaction_detail.set_recurrence(recurrence)
        if end_date is not None:
            self.ew.wait_till_element_is_visible(
                self.transaction_detail.SAVE_TRANSACTION_BUTTON, 5)
            self.ew.swipe_if_element_not_present(
                self.transaction_detail.END_DATE)
            self.transaction_detail.set_end_date(end_date)
        if reminder is not None:
            self.ew.wait_till_element_is_visible(
                self.transaction_detail.SAVE_TRANSACTION_BUTTON, 5)
            self.ew.swipe_if_element_not_present(
                self.transaction_detail.REMINDER)
            self.transaction_detail.set_reminder(reminder)
        self.ew.wait_till_element_is_visible(
            self.transaction_detail.SAVE_TRANSACTION_BUTTON, 5)

    def save_transaction(self):
        """Clicks on save transaction button"""
        self.ew.wait_and_tap_element(
            self.transaction_detail.SAVE_TRANSACTION_BUTTON, 5)
        if self.transfer_destination_modal.is_destination_modal_present(
        ) or self.transfer_destination_modal.is_origination_modal_present():
            self.transfer_destination_modal.create_as_new_transaction()

    def open_transaction(self):
        """Opens existing transaction, if there is no one, it creates transaction"""
        self.ew.wait_till_element_is_visible(
            self.timeline_general.OVERVIEW_BUTTON, 30)
        self.timeline_general.go_to_timeline()
        if self.ew.is_element_present(self.EXISTING_TRANSACTION) is False:
            self.create_transaction(transaction_type="random",
                                    category="random",
                                    amount="random",
                                    currency=None,
                                    wallet=None,
                                    start_date=None,
                                    note=None,
                                    label=None,
                                    photo=None,
                                    recurrence=None,
                                    end_date=None,
                                    reminder=None)
            self.save_transaction()
            self.ew.wait_till_element_is_visible(
                self.timeline_general.NAVIGATION_TIMELINE, 30)
        self.ew.wait_and_tap_element(self.EXISTING_TRANSACTION, 15)
        self.ew.wait_till_element_is_visible(
            self.transaction_detail.TRANSACTION_HEADER_TITLE, 15)

    def open_transaction_template(self):
        """Opens existing transaction template, if there is no one, it creates transaction"""
        self.ew.wait_till_element_is_visible(
            self.timeline_general.TRANSACTION_SECTION, 60)
        if self.ew.is_element_present(self.timeline_general.SCHEDULED) is True:
            self.timeline_general.open_scheduled_section()
            for i in self.EXISTING_TRANSACTION_TEMPLATES:
                if self.ew.is_element_present(i):
                    self.ew.tap_element(i)
                    break
                elif i == "Existing Item: regular-every year":
                    self.create_transaction(transaction_type="random",
                                            category="random",
                                            amount="random",
                                            currency=None,
                                            wallet=None,
                                            start_date=None,
                                            note=None,
                                            label=None,
                                            photo=None,
                                            recurrence="random",
                                            end_date=None,
                                            reminder=None)
                    self.save_transaction()
                    self.timeline_general.open_scheduled_section()
                    for i in self.EXISTING_TRANSACTION_TEMPLATES:
                        if self.ew.is_element_present(i):
                            self.ew.tap_element(i)
        else:
            self.create_transaction(transaction_type="random",
                                    category="random",
                                    amount="random",
                                    currency=None,
                                    wallet=None,
                                    start_date=None,
                                    note=None,
                                    label=None,
                                    photo=None,
                                    recurrence="random",
                                    end_date=None,
                                    reminder=None)
            self.save_transaction()
            self.timeline_general.open_scheduled_section()
            for i in self.EXISTING_TRANSACTION_TEMPLATES:
                if self.ew.is_element_present(i):
                    self.ew.tap_element(i)

    def edit_transaction(self, transaction_type, category, amount, wallet,
                         start_date, note, label, photo, recurrence, end_date,
                         reminder):
        """Edits requested attributes on transaction detail screen
        :param transaction_type: str or None
        :param category: str or None
        :param amount: str or None
        :param wallet: str or None
        :param start_date: str or None
        :param note: str or None
        :param label: str or None
        :param photo: bool
        :param recurrence: str or None
        :param end_date: str or None
        :param reminder: str or None
        """
        if transaction_type is not None:
            self.ew.wait_and_tap_element(self.transaction_detail.CATEGORY_ICON,
                                         10)
            if transaction_type == "transfer":
                self.transaction_detail.set_type_to_transfer()
            else:
                self.transaction_detail.set_type_of_transaction(
                    transaction_type)
                self.transaction_detail.set_category("random")
        if category is not None:
            self.ew.wait_and_tap_element(self.transaction_detail.CATEGORY_ICON,
                                         10)
            self.transaction_detail.set_category(category)
        if amount is not None:
            self.ew.wait_and_tap_element(self.transaction_detail.AMOUNT_INPUT,
                                         10)
            self.ew.wait_till_element_is_visible(
                self.transaction_detail.NUMPAD_CLEAR, 10)
            for i in range(6):
                self.ew.tap_element(self.transaction_detail.NUMPAD_CLEAR)
            self.transaction_detail.set_amount(amount)
        if wallet is not None:
            self.transaction_detail.set_wallet(wallet, "transaction")
        if start_date is not None:
            self.transaction_detail.set_start_date(start_date)
        if note is not None:
            try:
                self.ew.wait_till_element_is_visible(
                    self.transaction_detail.SAVE_TRANSACTION_BUTTON, 5)
                self.ew.get_element(
                    self.transaction_detail.EXISTING_NOTE).clear()
            except NoSuchElementException:
                pass
            self.transaction_detail.set_note(note)
        if label is not None:
            self.transaction_detail.set_label(label)
        if photo is not None:
            self.transaction_detail.set_photo()
        if recurrence is not None:
            self.ew.wait_till_element_is_visible(
                self.transaction_detail.SAVE_TRANSACTION_BUTTON, 5)
            self.ew.swipe_if_element_not_present(
                self.transaction_detail.RECURRENCE)
            self.transaction_detail.set_recurrence(recurrence)
        if end_date is not None:
            self.ew.wait_till_element_is_visible(
                self.transaction_detail.SAVE_TRANSACTION_BUTTON, 5)
            self.ew.swipe_if_element_not_present(
                self.transaction_detail.END_DATE)
            self.transaction_detail.set_end_date(end_date)
        if reminder is not None:
            self.ew.wait_till_element_is_visible(
                self.transaction_detail.SAVE_TRANSACTION_BUTTON, 5)
            self.ew.swipe_if_element_not_present(
                self.transaction_detail.REMINDER)
            self.transaction_detail.set_reminder(reminder)
        self.ew.wait_till_element_is_visible(
            self.transaction_detail.SAVE_TRANSACTION_BUTTON, 5)

    def delete_transaction(self):
        """Deletes transaction from transaction detail screen"""
        self.ew.wait_and_tap_element(self.transaction_detail.TRASH_ICON, 10)
        self.ew.wait_and_tap_element(self.transaction_detail.DELETE_BUTTON, 10)
Ejemplo n.º 10
0
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 TransferTemplateValidator:
    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_template_validator = TransactionTemplateValidator(
            self.driver)
        self.transaction_validator = TransactionValidator(self.driver)
        self.transfer_validator = TransferValidator(self.driver)

    def get_all_attributes(self):
        """ Getting all attributes of transfer template
        :return: dict
        """
        all_attributes = {
            "amount":
            self.transaction_detail.get_amount(),
            "currency":
            self.transaction_detail.get_currency(),
            "wallet_amount":
            self.transaction_detail.get_wallet_amount(),
            "outgoing_wallet":
            self.transaction_detail.get_wallet("transfer_outgoing"),
            "incoming_wallet":
            self.transaction_detail.get_wallet("transfer_incoming"),
            "start_date":
            self.transaction_detail.get_date("start"),
            "note":
            self.transaction_detail.get_note(),
            "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_transfer_template_on_timeline(self, attributes):
        """ Checking if transfer template is visible inside Scheduled section
        :param attributes: dict
        :return: bool
        """
        if "Out of Spendee" not in [
                attributes['outgoing_wallet'], attributes['incoming_wallet']
        ]:
            is_two_way_transfer = True
        else:
            is_two_way_transfer = False

        transfer_locator = f"transfer/" \
                           f"undefined/" \
                           f"{self.transfer_validator.adjust_amounts(attributes['amount'], attributes['wallet_amount'], attributes['currency'], attributes['outgoing_wallet'], attributes['incoming_wallet'])[0]}/" \
                           f"{self.transfer_validator.adjust_amounts(attributes['amount'], attributes['wallet_amount'], attributes['currency'], attributes['outgoing_wallet'], attributes['incoming_wallet'])[1]}/" \
                           f"{self.transfer_validator.adjust_wallets(attributes['outgoing_wallet'], attributes['incoming_wallet'])[0]}/" \
                           f"{self.transfer_validator.adjust_wallets(attributes['outgoing_wallet'], attributes['incoming_wallet'])[1]}/" \
                           f"{self.transaction_validator.adjust_note(attributes['note'])}/" \
                           f"undefined/" \
                           f"false/" \
                           f"{self.transaction_template_validator.adjust_recurrence(attributes['recurrence'])}/" \
                           f"{self.transaction_template_validator.adjust_end_date(attributes['end_date'])}/" \
                           f"{self.transaction_validator.adjust_reminder(attributes['reminder'])}"

        print(f'LOCATOR: {transfer_locator}')

        if is_two_way_transfer:
            _, _, amount, wallet_amount, outgoing_wallet, incoming_wallet, _, _, _, recurrence, _, _ = (
                str(x) for x in transfer_locator.split('/'))
            s_out = transfer_locator.split("/")
            s_in = transfer_locator.split("/")

            s_out[2] = f"-{amount}"
            if wallet_amount != "undefined":
                s_out[3] = f"-{wallet_amount}"

            if recurrence == "undefined":
                s_in[4] = incoming_wallet
                s_in[5] = outgoing_wallet

            transfer_outgoing_locator = '/'.join(s_out)
            transfer_incoming_locator = '/'.join(s_in)

            print(f'OUTGOING LOCATOR: {transfer_outgoing_locator}')
            print(f'INCOMING LOCATOR: {transfer_incoming_locator}')

        self.transaction_validator.prepare_timeline(
            attributes['start_date'],
            self.transaction_template_validator.adjust_recurrence(
                attributes['recurrence']))

        android_timeout = time.time() + 60
        ios_timeout = time.time() + 5
        res = self.rs.get_resolution()

        if is_two_way_transfer:
            locator = transfer_outgoing_locator
        else:
            locator = transfer_locator
        is_transfer_present = self.ew.is_element_present(locator)
        while is_transfer_present is False:
            if PLATFORM == "Android":
                self.transaction_validator.swipe_android(res)
                is_transfer_present = self.ew.is_element_present(locator)
                if time.time() > android_timeout:
                    return False
            else:
                is_transfer_present = self.ew.is_element_present(locator)
                if time.time() > ios_timeout:
                    return False
        if is_two_way_transfer and self.ew.is_element_present(
                transfer_incoming_locator) is False:
            return False
        return True
Ejemplo n.º 12
0
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
Ejemplo n.º 13
0
class CategoryValidator:
    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 get_all_attributes(self):
        """ Getting all attributes of category
        :return: dict
        """
        all_attributes = {
            "name": self.category_detail.get_name(),
            "color": self.category_detail.get_color(),
            "image": self.category_detail.get_image()
        }

        return all_attributes

    def is_category_existing(self, attributes):
        """ Checking if category is visible in category list
        :param attributes: dict
        :return: bool
        """
        category_locator = f"{attributes['name']}/" \
                           f"{attributes['color']}/" \
                           f"{attributes['image']}"

        print(f'ATTRIBUTES: {attributes}')
        print(f'LOCATOR: {category_locator}')

        android_timeout = time.time() + 30
        ios_timeout = time.time() + 5
        res = self.rs.get_resolution()
        is_category_present = self.ew.is_element_present(category_locator)
        while is_category_present is False:
            if PLATFORM == "Android":
                self.action.long_press(None, self.rs.all_resolutions[f"{res}"]["x"],
                                       self.rs.all_resolutions[f"{res}"]["categories_y_start"]) \
                    .move_to(None, self.rs.all_resolutions[f"{res}"]["x"],
                             self.rs.all_resolutions[f"{res}"]["categories_y_end"]) \
                    .release().perform()
                is_category_present = self.ew.is_element_present(
                    category_locator)
                if time.time() > android_timeout:
                    return False
            else:
                is_category_present = self.ew.is_element_present(
                    category_locator)
                if time.time() > ios_timeout:
                    return False
        return True

    def get_selected_categories(self):
        """ Gets all values of selected categories in merge process
        :return: tuple
        """
        categories = self.ew.get_attributes(
            self.categories_general.CATEGORY_INFO, "content-desc")
        name1, color1, image1 = categories[0].split('/')
        attributes1 = {"name": name1, "color": color1, "image": image1}
        name2, color2, image2 = categories[1].split('/')
        attributes2 = {"name": name2, "color": color2, "image": image2}
        return (attributes1, attributes2)
Ejemplo n.º 14
0
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"))
Ejemplo n.º 15
0
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()
Ejemplo n.º 16
0
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()
Ejemplo n.º 17
0
class TransferActions():
    EXISTING_TRANSFER = "Existing Item: transfer-undefined"
    EXISTING_TRANSFER_TEMPLATES = ["Existing Item: transfer-every day", "Existing Item: transfer-every 2 days",
                                   "Existing Item: transfer-every working day", "Existing Item: transfer-every week",
                                   "Existing Item: transfer-every 2 weeks", "Existing Item: transfer-every 4 weeks",
                                   "Existing Item: transfer-every month", "Existing Item: transfer-every 2 months",
                                   "Existing Item: transfer-every 3 months", "Existing Item: transfer-every 6 months",
                                   "Existing Item: transfer-every year"]

    def __init__(self, driver):
        self.driver = driver
        self.ew = ElementWrapper(self.driver)
        self.timeline_general = TimelineGeneral(self.driver)
        self.transaction_actions = TransactionActions(self.driver)
        self.transaction_detail = TransactionDetail(self.driver)

    def create_transfer(self, amount, outgoing_wallet, incoming_wallet, start_date, note, recurrence, end_date,
                        reminder):
        """ Opens create transfer screen and sets requested attributes
        :param amount: str or None
        :param outgoing_wallet: str or None
        :param incoming_wallet: str or None
        :param start_date: str or None
        :param note: str or None
        :param recurrence: str or None
        :param end_date: str or None
        :param reminder: str or None
        """
        self.timeline_general.open_transaction_create_screen()
        self.transaction_detail.set_type_to_transfer()
        self.transaction_detail.set_amount(amount)
        if outgoing_wallet is not None:
            self.transaction_detail.set_wallet(outgoing_wallet, "transfer_outgoing")
        if incoming_wallet is not None:
            self.transaction_detail.set_wallet(incoming_wallet, "transfer_incoming")
        if start_date is not None:
            self.transaction_detail.set_start_date(start_date)
        if note is not None:
            self.transaction_detail.set_note(note)
        if recurrence is not None:
            self.transaction_detail.set_recurrence(recurrence)
        if end_date is not None:
            self.transaction_detail.set_end_date(end_date)
        if reminder is not None:
            self.transaction_detail.set_reminder(reminder)

    def open_transfer(self):
        """Opens existing transfer, if there is no one, it creates transfer"""
        self.timeline_general.go_to_timeline()
        self.ew.wait_till_element_is_visible(self.timeline_general.ADD_TRANSACTION_BUTTON, 30)
        print(self.ew.is_element_present(self.EXISTING_TRANSFER))
        if self.ew.is_element_present(self.EXISTING_TRANSFER) is False:
            self.create_transfer(amount="random", outgoing_wallet=None, incoming_wallet=None, start_date=None,
                                 note=None, recurrence=None, end_date=None, reminder=None)
            self.transaction_actions.save_transaction()
            self.ew.wait_till_element_is_visible(self.timeline_general.NAVIGATION_TIMELINE, 30)
        self.ew.wait_and_tap_element(self.EXISTING_TRANSFER, 15)
        self.ew.wait_till_element_is_visible(self.transaction_detail.TRANSACTION_HEADER_TITLE, 15)

    def open_transfer_template(self):
        """Opens existing transfer template"""
        self.ew.wait_till_element_is_visible(self.timeline_general.TRANSACTION_SECTION, 60)
        if self.ew.is_element_present(self.timeline_general.SCHEDULED) is True:
            self.timeline_general.open_scheduled_section()
            for i in self.EXISTING_TRANSFER_TEMPLATES:
                if self.ew.is_element_present(i):
                    self.ew.tap_element(i)
                    break
                elif i == "Existing Item: transfer-every year":
                    self.create_transfer(amount="random", outgoing_wallet=None, incoming_wallet=None, start_date=None,
                                         note=None, recurrence="random", end_date=None, reminder=None)
                    self.transaction_actions.save_transaction()
                    self.timeline_general.open_scheduled_section()
                    for i in self.EXISTING_TRANSFER_TEMPLATES:
                        if self.ew.is_element_present(i):
                            self.ew.tap_element(i)
        else:
            self.create_transfer(amount="random", outgoing_wallet=None, incoming_wallet=None, start_date=None,
                                 note=None, recurrence="random", end_date=None, reminder=None)
            self.transaction_actions.save_transaction()
            self.timeline_general.open_scheduled_section()
            for i in self.EXISTING_TRANSFER_TEMPLATES:
                if self.ew.is_element_present(i):
                    self.ew.tap_element(i)

    def edit_transfer(self, transaction_type, amount, outgoing_wallet, incoming_wallet, start_date, note, recurrence,
                      end_date, reminder):
        """ Edits requested attributes on transfer detail screen
        :param transaction_type: str or None
        :param amount: str or None
        :param outgoing_wallet: str or None
        :param incoming_wallet: str or None
        :param start_date: str or None
        :param note: str or None
        :param recurrence: str or None
        :param end_date: str or None
        :param reminder: str or None
        """
        if transaction_type is not None:
            self.ew.tap_element(self.transaction_detail.CATEGORY_ICON)
            if transaction_type == "transfer":
                self.transaction_detail.set_type_to_transfer()
            else:
                self.transaction_detail.set_type_of_transaction(transaction_type)
                self.transaction_detail.set_category("random")
        if amount is not None:
            self.ew.tap_element(self.transaction_detail.AMOUNT_INPUT)
            self.ew.wait_till_element_is_visible(self.transaction_detail.NUMPAD_CLEAR, 10)
            for i in range(6):
                self.ew.wait_and_tap_element(self.transaction_detail.NUMPAD_CLEAR, 5)
            self.transaction_detail.set_amount(amount)
        if outgoing_wallet is not None:
            if self.transaction_detail.get_wallet("transfer_outgoing") == "Out of Spendee":
                self.transaction_detail.set_wallet(outgoing_wallet, "transfer_outgoing")
        if incoming_wallet is not None:
            if self.transaction_detail.get_wallet("transfer_incoming") == "Out of Spendee":
                self.transaction_detail.set_wallet(incoming_wallet, "transfer_incoming")
        if start_date is not None:
            self.transaction_detail.set_start_date(start_date)
        if note is not None:
            try:
                self.ew.get_element(self.transaction_detail.EXISTING_NOTE).clear()
            except NoSuchElementException:
                pass
            self.transaction_detail.set_note(note)
        if recurrence is not None:
            self.transaction_detail.set_recurrence(recurrence)
        if end_date is not None:
            self.transaction_detail.set_end_date(end_date)
        if reminder is not None:
            self.ew.wait_till_element_is_visible(self.transaction_detail.SAVE_TRANSACTION_BUTTON, 5)
            self.ew.swipe_if_element_not_present(self.transaction_detail.REMINDER)
            self.transaction_detail.set_reminder(reminder)
        self.ew.wait_till_element_is_visible(self.transaction_detail.SAVE_TRANSACTION_BUTTON, 5)