示例#1
0
    def open_item_by_name_in_main_menu(self, name: str) -> None:
        """ Открыть раздел сайта по имени в главном меню """

        assert name in self.main_menu, f"Нет пункта {name} в главном меню"

        txb_menu_item = BaseElement(
            self.base_admin_locators['txbMenuItemByName'].format(name))
        txb_menu_item.click()
示例#2
0
    def open_site_by_link_in_header(self) -> None:
        """ Открытие главной страницы сайта по ссылке из шапки """

        tabs_in_browser = self._browser.window_handles
        txb_site_name_link = BaseElement(
            self.base_admin_locators['txbSiteNameLink'])
        txb_site_name_link.click()
        WebDriverWait(self._browser, 10).until(
            lambda browser: len(browser.window_handles) > len(tabs_in_browser))
示例#3
0
        def __init__(self, browser: webdriver):
            self._browser = browser

            self.products = []
            self.errors = []

            div_products = self._browser.find_elements_by_xpath(self.locators['divProducts'])
            for div_product in div_products:
                html = etree.parse(StringIO(div_product.get_property('outerHTML')), parser=etree.HTMLParser())

                # Название товара
                name_element = BaseElement(self.locators['txbName'], context=div_product)

                # Цена за единицу продукта
                price_per_product = html.xpath(self.locators['txbPricePerProduct'])[0].text

                # Поле с количеством
                quantity_element = BaseElement(self.locators['inpQuantity'], context=div_product)

                # Итогова цена за товар
                price_amount = convert_price_from_str_to_float(html.xpath(self.locators['txbPriceAmount'])[0].text)
                try:
                    # Итоговая цена без скидки
                    price_amount_old = convert_price_from_str_to_float(
                        html.xpath(self.locators['txbPriceAmountOld'])[0].text)
                except IndexError:
                    price_amount_old = None

                # Элемент удаления товара из корзины
                delete_element = BaseElement(self.locators['btnDelete'], context=div_product)

                # Сообщение о количестве товара в магазине
                try:
                    count_message = html.xpath(self.locators['txbProductCount'])[0].text
                except IndexError:
                    count_message = None

                self.products.append({
                    'name': name_element.text + self._get_params(html),  # название товара
                    'price_per_product': convert_price_from_str_to_float(price_per_product),  # цена за единицу продукта
                    'quantity': int(quantity_element.ge().get_property('value')),  # количество товара
                    'price_amount': price_amount,  # итогова цена за товар
                    'price_amount_old': price_amount_old,  # итоговая цена без скидки
                    'count_message': count_message,  # сообщение о количеством товара в магазине
                    'elements': {
                        'name': name_element,  # элемент название товара
                        'quantity': quantity_element,  # элемент количество товара
                        'delete': delete_element  # элемент удаления товара из корзины
                    }
                })

                self._error_in_quantity(self.products[-1]['name'], quantity_element, count_message)
示例#4
0
    def open_item_by_names_in_left_menu(self, menu_item: str,
                                        sub_menu_item: str) -> None:
        """ Открыть раздел сайта по имени раздела и пункта в левом меню """

        menu_item_parent_element = BaseElement(
            self.base_admin_shop_locators['txbMenu'].format(menu_item) + "/..")

        if 'is-open' not in menu_item_parent_element.ge().get_attribute(
                'class'):
            # Если родительская категория не раскрыта, раскрываю
            BaseElement(self.base_admin_shop_locators['txbMenu'].format(
                menu_item)).click()

        # Открываю подменю
        BaseElement(self.base_admin_shop_locators['txbSubMenu'].format(
            sub_menu_item)).click()
示例#5
0
        def __init__(self, browser: webdriver):
            self._browser = browser

            self.deliveries = []

            div_deliveries = self._browser.find_elements_by_xpath(self.locators['divDeliveries'])
            for div_delivery in div_deliveries:
                html = etree.parse(StringIO(div_delivery.get_property('outerHTML')), parser=etree.HTMLParser())

                # Название метода
                name_element = BaseElement(self.locators['txbName'], context=div_delivery)

                # Стоимость доставки
                price = convert_price_from_str_to_float(html.xpath(self.locators['txbPrice'])[0].text)

                # Стоимость доставки без скидки
                try:
                    old_price = convert_price_from_str_to_float(html.xpath(self.locators['txbPriceOld'])[0].text)
                except IndexError:
                    old_price = None

                self.deliveries.append({
                    'name': name_element.text,  # название метода
                    'price': price,  # стоимость
                    'old_price': old_price,  # стоимость без скидки
                    'elements': {
                        'name': name_element  # элемент названия метода
                    }
                })
示例#6
0
        def get_applied_name(self) -> str:
            """ Получить имя примененного промокода """

            try:
                return BaseElement(self.locators['inpField'], 2, True).ge().get_attribute('value')
            except Exception:
                return ""
示例#7
0
    def is_it_empty_shop_cart_page(self) -> bool:
        """ Проверяем что открыта пустая корзина """

        try:
            BaseElement(self.locators['divEmptyShopCartPage'], 1)
            return True
        except AssertionError:
            return False
示例#8
0
    def is_it_the_right_page(self) -> bool:
        """ Определяем что текущая страница правильная, если на ней есть элемент page_locator """

        try:
            BaseElement(self.page_locator, wait_seconds=20)
            return True
        except AssertionError:
            return False
示例#9
0
        def is_applied(self) -> bool:
            """ Проверяем, что промокод применен """

            try:
                BaseElement(self.locators['txbMessage'], 1)
                return True
            except AssertionError:
                return False
示例#10
0
    def is_order_number_exist(self, order_number: str) -> bool:
        """ Проверка существования заказа с заданным номером """

        try:
            BaseElement(self.locators['txbOrderNumber'].format(value=order_number))
            return True
        except NoSuchElementException:
            return False
示例#11
0
        def delete_by_name(self, product_name: str) -> None:
            """ Удалить указанный товар """

            time.sleep(1)
            self.products[self._get_index_by_name(product_name)]['elements']['delete'].click()
            time.sleep(2)
            # Подтверждения удаления товара
            BaseElement(self.locators['btnConfirmDelete']).click()
            FrontShopCartPage(is_wait=True)
示例#12
0
        def submit_form(self) -> bool:
            """ Оформляем заказ """

            FrontShopCartPage(is_wait=True)

            try:
                BaseElement(self.locators['btnSubmit'], 2).click()
                return True
            except ElementClickInterceptedException:
                return False
示例#13
0
        def activate(self, promo_code: str) -> None:
            """ Активировать промокод """

            # Проверяем, что в корзине нет активированного промокода
            applied_promo_code = self.get_applied_name()
            assert not applied_promo_code, f"В корзине уже активирован промокод '{applied_promo_code}'"

            # Если отображается текст, активируем поле ввода промокода
            try:
                BaseElement(self.locators['txbLink'], 1).click()
            except AssertionError:
                pass

            # Вводим промокод
            BaseElement(self.locators['inpField']).set_text(promo_code)

            # Нажимаем применить промокод
            BaseElement(self.locators['txbApply']).click()

            FrontShopCartPage(is_wait=True)
示例#14
0
        def _error_check_message(self) -> None:
            """ Проверка промокода на наличие ошибок """

            try:
                message = BaseElement(self.locators['txbError'], 0).text
                if message == "Can not apply.":
                    self.errors.append(('promocode_cant_apply', True))
                elif message == "123":
                    self.errors.append(('promocode_not_exist', True))
                else:
                    self.errors.append(('promocode', message))
            except AssertionError:
                pass
示例#15
0
        def _error_in_quantity(self, product_name: str, inp_quantity: BaseElement, count_message: str) -> None:
            """ Поле количество указанного товара """

            error = 0

            if "isError__" in inp_quantity.ge().get_attribute('class'):
                error += 1

            if count_message:
                error += 1

            if error == 2:
                self.errors.append(('product_quantity', product_name))
示例#16
0
        def __init__(self):
            total_price = convert_price_from_str_to_float(BaseElement(self.locators['txbTotalPrice'], 3).text)

            try:
                total_price_old = convert_price_from_str_to_float(
                    BaseElement(self.locators['txbTotalPriceOld'], 0).text)
            except AssertionError:
                total_price_old = None

            amount_price = convert_price_from_str_to_float(BaseElement(self.locators['txbAmountPrice'], 3).text)

            try:
                amount_price_old = convert_price_from_str_to_float(
                    BaseElement(self.locators['txbAmountPriceOld'], 0).text)
            except AssertionError:
                amount_price_old = None

            self.prices = {
                'total_price': total_price,
                'total_price_old': total_price_old,
                'amount_price': amount_price,
                'amount_price_old': amount_price_old,
            }
示例#17
0
        def _error_form_fields_are_red(self, names: list = None) -> None:
            """ Незаполненные формы должны подсветиться красным """
            error_field_names = []

            if not names:
                names = [item[0] for item in self.default_fields]

            for name in names:
                try:
                    BaseElement(self.locators['inpFieldRed'].format(value=name), 0)
                except AssertionError:
                    error_field_names.append(name)

            if error_field_names:
                self.errors.append(('form_fields_not_red', error_field_names))
示例#18
0
        def fill_form(self, fields: list) -> None:
            """ Заполняем форму заказа
                fields: [(name, value), (name, value), ...] """

            names_without_check = []

            names = [field[0] for field in fields]

            for default_field in self.default_fields:
                if default_field[0] not in names:
                    fields.append(default_field)
                    names_without_check.append(default_field[0])

            for field in fields:
                try:
                    BaseElement(self.locators['inpField'].format(value=field[0]), 0).set_text(field[1])
                except AssertionError:
                    assert field[0] not in names_without_check, f"Не удалось найти поле '{field[0]}' в форме"
示例#19
0
        def _error_check_under_form(self) -> None:
            """ Проверка формы на наличие ошибок """

            try:
                BaseElement(self.locators['txbErrors'], 0)

                errors = self._browser.find_elements_by_xpath(self.locators['txbErrors'])
                for error in errors:
                    if error.text == "Стоимость изенилась":
                        self.errors.append(('amount_price_change', True))
                    elif error.text == "Такой доставки нет":
                        self.errors.append(('delivery_method_unavailable', True))
                    elif error.text == "Такой платежки нет":
                        self.errors.append(('payment_method_unavailable', True))
                    else:
                        self.errors.append(('under_form', error.text))
            except AssertionError:
                pass
示例#20
0
        def __init__(self, browser: webdriver):
            self._browser = browser

            self.payments = []

            div_payments = self._browser.find_elements_by_xpath(self.locators['divPayments'])
            for div_payment in div_payments:
                if not div_payment.is_displayed:
                    # Метод оплаты не отображается
                    continue

                html = etree.parse(StringIO(div_payment.get_property('outerHTML')), parser=etree.HTMLParser())

                # Описание
                try:
                    description = html.xpath(self.locators['txbDescription'])[0].text
                except IndexError:
                    description = None

                # Название метода
                name_element = BaseElement(self.locators['txbName'], context=div_payment)

                if description:
                    name = re.search(r"(.+)\n", name_element.text).group(1)
                else:
                    name = name_element.text

                # Комиссия
                price = html.xpath(self.locators['txbPrice'])[0].text

                if price:
                    price = convert_price_from_str_to_float(price)
                else:
                    price = None

                self.payments.append({
                    'name': name,  # название метода
                    'description': description,  # описание
                    'price': price,  # комиссия
                    'elements': {
                        'name': name_element  # элемент названия метода
                    }
                })
示例#21
0
    def _parse_page(self) -> dict:
        """ Распарсить страницу товара """

        elements = {}

        # Определение контекста, для парсинга информации на странице
        div_description = BaseElement(self.locators['locDescription'])
        div_description_html = etree.parse(StringIO(
            div_description.ge().get_property('outerHTML')),
                                           parser=etree.HTMLParser())

        # Название товара
        name = div_description_html.xpath(
            self.locators['txtName'])[0].text.strip()

        # Артикул
        vendor_code = None

        temp = div_description_html.xpath(self.locators['txtVendorCode'])
        if temp[0].text is not None:
            temp = temp[0].text.strip()
            if temp:
                vendor_code = {
                    'text': re.sub(r"\s+", " ", temp),
                    'code': re.search(r":\s*(.*)$", temp).group(1).rstrip()
                }

        # Цена и цена от..
        price = None
        price_from = None

        temp = div_description_html.xpath(self.locators['txtPrice'])
        if temp[0].text is not None:
            if "от" in temp[0].text or (temp[0].getparent().text is not None
                                        and "от" in temp[0].getparent().text):
                price_from = convert_price_from_str_to_float(
                    temp[0].text.replace("\xa0", " "))
            else:
                price = convert_price_from_str_to_float(temp[0].text)

        # Цена со скидкой
        price_discount = None

        temp = div_description_html.xpath(self.locators['txtPriceDiscount'])
        if len(temp):
            temp = temp[0].text
            if temp:
                price_discount = convert_price_from_str_to_float(temp)

        # Параметры
        params = None

        div_params = div_description_html.xpath(self.locators['locParams'])
        if len(div_params):
            params = []

            for div_param in div_params:
                # id параметра
                param_id = int(
                    div_param.xpath(
                        self.locators['locParamId'])[0].attrib['name'])

                # выбранное значнеие
                selected = div_param.xpath(
                    self.locators['txtParamSelected'])[0].text

                # Значения
                values = []

                div_values = div_param.xpath(self.locators['locParamValues'])
                for div_value in div_values:
                    # Проверяем отображение значения параметра
                    try:
                        disabled = True if div_value.attrib[
                            'disabled'] else False
                    except KeyError:
                        disabled = False

                    values.append({
                        'id':
                        int(div_value.attrib['data-value']),  # id значения
                        'name': div_value.text,  # имя значения
                        'disabled': disabled,  # отображается ли он
                    })
                params.append({
                    'id': param_id,  # id параметра
                    'selected': selected,  # выбранное значение
                    'values': values,  # словарь значений
                })

        # Поле с количеством
        quantity = None

        temp = div_description_html.xpath(self.locators['inpQuantity'])
        if len(temp):
            quantity = int(temp[0].attrib['value'])  # количество

            elements['quantity_minus'] = BaseElement(
                self.locators['btnQuantityMinus'])
            elements['quantity'] = BaseElement(self.locators['inpQuantity'])
            elements['quantity_plus'] = BaseElement(
                self.locators['btnQuantityPlus'])

        # Кнопка
        button = None

        temp = div_description_html.xpath(self.locators['btnAdd'] + "/span")
        if len(temp):
            button_text = temp[0].text.strip()

            if "Заказать" in button_text:
                button_type = 'preOrder'
            else:
                button_type = 'addToCard'

            button = {
                'text': button_text,  # текст внутри
                'type': button_type,  # тип
            }

            # Элемент кнопка
            elements['button'] = BaseElement(self.locators['btnAdd'])
        else:
            temp = div_description_html.xpath(self.locators['btnPreOrder'] +
                                              "/span")
            if len(temp):
                button = {
                    'text': temp[0].text.strip(),  # текст внутри
                    'type': 'preOrder',  # тип
                }

                # Элемент кнопка
                elements['button'] = BaseElement(self.locators['btnPreOrder'])

        # Количестве товара
        count = None

        temp = div_description_html.xpath(self.locators['locCount'])
        if len(temp):
            text = temp[0].xpath("string()").strip()
            if text:
                text = re.sub(r"\s+", " ", text)

                count = {
                    'text':
                    text,  # текст сообщения
                    'number':
                    int(
                        div_description_html.xpath(self.locators['locCount'] +
                                                   "/span")[0].text),
                }

        result = {
            'name': name,  # название товара
            'vendor_code': vendor_code,  # артикул
            'price': price,  # цена
            'price_from': price_from,  # цена от..
            'price_discount': price_discount,  # цена со скидкой
            'params': params,  # словарь параметров
            'quantity': quantity,  # количество
            'button': button,  # словарь кнопки
            'count': count,  # словарь количества товара в наличии
            'elements': elements  # словарь элементов
        }

        return result
示例#22
0
    def open_product_by_name(self, product_name: str) -> None:
        """ Открыть продукт по имени """

        BaseElement(self.locators['productName'].format(product_name)).click()
示例#23
0
    def open_last_order(self) -> None:
        """ Открыть последний заказ """
        self._browser.refresh()

        BaseElement(self.locators['txbLastOrder']).click()
示例#24
0
    def click_on_button_add_to_cart(self) -> None:
        """ Нажать на кнопку 'Добавить в корзину' """

        BaseElement(self.locators['btnAddToCart']).click()
        time.sleep(2.5)
示例#25
0
    def click_on_button_save(self):
        """ Стандартная кнопка сохранения для магазина """

        BaseElement(self.base_admin_shop_locators['btnSubmit']).click()

        time.sleep(1)
示例#26
0
    def get_order_number(self) -> str:
        """ Извлечение номера заказа """

        txb_order_number = BaseElement(self.locators["txbOrderTitle"]).text
        return re.search(r"(\d{6})", txb_order_number).group(0)
示例#27
0
    def get_price_by_order_number(self, order_number: str) -> float:
        """ Получить сумму заказа по номеру заказа """

        txb_price = BaseElement(self.locators['txbPriceByOrderNumber'].format(value=order_number)).text
        return convert_price_from_str_to_float(txb_price)
示例#28
0
    def login(self, name: str = None, password: str = None) -> None:
        """ Метод логина в админку сайта """

        inp_login = BaseElement(self.locators['inpLogin'])
        name = name or TEST_SITE['login_name']
        inp_login.set_text(name)

        inp_password = BaseElement(self.locators['inpPassword'])
        password = password or TEST_SITE['login_password']
        inp_password.set_text(password)

        btn_login = BaseElement(self.locators['btnLogin'])
        btn_login.click()
示例#29
0
 def _error_min_order_message(self) -> None:
     try:
         self.errors.append(('min_order_message', BaseElement(self.locators['txbMinOrderMessage'], 0).text))
     except AssertionError:
         pass
示例#30
0
    def _get_order(self) -> dict:
        order = {}

        div_order_data = BaseElement(self.locators['locOrderData'])
        html = etree.parse(StringIO(
            div_order_data.ge().get_property('outerHTML')),
                           parser=etree.HTMLParser())
        div_fields = html.xpath(self.locators['locOrderDataFields'])

        temp = div_fields[0].text
        order['number'] = re.search(r"(\d{6})", temp).group(0)

        temp = div_fields[1].text
        order['date'] = re.search(r"Дата:\s*(.*)$", temp).group(1)

        temp = div_fields[2].text
        order['type'] = re.search(r"Тип:\s*(.*)$", temp).group(1)

        order['status'] = div_fields[3].xpath(
            self.locators['btnOrderDataField'])[0].attrib['title']
        order['delivery'] = div_fields[4].xpath(
            self.locators['btnOrderDataField'])[0].attrib['title']
        order['payment'] = div_fields[5].xpath(
            self.locators['btnOrderDataField'])[0].attrib['title']

        order['promocode'] = div_fields[-1].xpath(
            self.locators['btnOrderDataField'])[0].attrib['title']
        if len(order['promocode']) != 3:
            order['promocode'] = re.search(r"^(.*)\s-\s.*$",
                                           order['promocode']).group(1)

        order['form'] = []
        # for div_field in div_fields[6:-1]:
        #     order['form'].append(div_field.xpath(self.locators['inpOrderDataFields'])[0].attrib['value'])

        order['products'] = []
        order_table = BaseElement(self.locators['locOrderTable'])
        html = etree.parse(StringIO(
            order_table.ge().get_property('outerHTML')),
                           parser=etree.HTMLParser())
        tr_elements = html.xpath(".//tr")[:-5]
        for tr_element in tr_elements:
            vendor_code = tr_element.xpath(
                ".//span[@class='vendor-code']")[0].text
            order['products'].append({
                'name':
                tr_element.xpath(".//td[@class='sku']")[0].text + "|" +
                vendor_code,
                'price_per_product':
                convert_price_from_str_to_float(
                    tr_element.xpath(".//td[@class='sku-price']")
                    [0].attrib['value']),
                'quantity':
                int(
                    tr_element.xpath(".//td[@class='sku-quantit']")
                    [0].attrib['value']),
                'price_amount':
                convert_price_from_str_to_float(
                    tr_element.xpath(".//td[@class='total-cost']")[0].text),
            })

        order['delivery_tax'] = convert_price_from_str_to_float(
            html.xpath(self.locators['inpDeliveryTax'])[0].attrib['value'])
        order['discount'] = convert_price_from_str_to_float(
            html.xpath(self.locators['inpDiscount'])[0].attrib['value'])
        order['markup'] = convert_price_from_str_to_float(
            html.xpath(self.locators['inpMarkup'])[0].attrib['value'])
        order['total_amount'] = convert_price_from_str_to_float(
            html.xpath(self.locators['txbTotalAmount'])[0].text)

        return order