def base_component_list_element(self, ele_class: T) -> List['T']:
     '''
     Because lazy initial finding we need to
     call __get__ method for finding element
     :param ele_class:
     :return: List of WebElement base on element class
     '''
     base_element = ElementFactory.get_list_element(
         ele_class, self.base_component_locator[0],
         self.base_component_locator[1])
     base_element()
     return base_element
class ConversationPage(BasePage):
    path_page = "/admin/conversations"
    list_conversations_container = ElementFactory.get_list_element(
        by=By.XPATH,
        locator="//*[contains(@class, 'list') and contains(@class,'conversations')]//*[contains(@class,'item')]",
        element_cls=BaseElement
    )

    def __init__(self):
        self.__loader_component = LoaderComponent()

    def open_conversation_page(self):
        self.open_page(path=self.path_page)

    def get_last_message(self, conversation_index=0):
        self.__loader_component.wait_for_component_invisible()
        txt_last_message = self.list_conversations_container[conversation_index].find_element(
            by=By.TAG_NAME,
            value="abbr",
        )
        return txt_last_message.text
Ejemplo n.º 3
0
class SectionWithGroupFAQ(BaseComponent):
    def __init__(self, section_name):
        BaseComponent.__init__(
            self, By.XPATH,
            f"//div[contains(@class,'knowledge-styles') and contains(@class,'accordion')"
            f" and .//*[normalize-space(text())='{section_name}']]")

    base_locator = "//div[contains(@class,'knowledge-styles') and contains(@class,'accordion')]"
    lbl_knowledge_title = ".//div[contains(@class,'title')]"  # /div
    btn_add_pair = ".//*[contains(@id,'add-pair-button')]"
    input_question_of_new_group = ".//div[@placeholder='Type a question']"
    input_answer_of_new_group = "//div[@placeholder='Type a question']/" \
                                "ancestor::tr//div[@placeholder='Type an answer']"
    tfoot_tag_name = "tfoot"
    div_header = ".//div[contains(@class,'title')]"
    row_contains_answer = ".//tr//div[@placeholder='Type an answer' and .='{0}']/ancestor::tr"
    row_contains_question = ".//tr/td[1]//span[.='{0}']/ancestor::tr"

    base_elements = ElementFactory.get_list_element(by=By.XPATH,
                                                    locator=base_locator,
                                                    element_cls=BaseElement)

    def get_section_info(self):
        lbl_title = self.get_list_child_element(BaseElement, By.XPATH,
                                                self.lbl_knowledge_title)

        result = {"title": lbl_title[0].text, "length": lbl_title[1].text}
        return result

    def is_active_section(self):
        title = self.get_child_element(BaseElement, By.XPATH,
                                       ".//div[contains(@class,'title')]")
        class_name = title.get_attribute('class')
        return ' active ' in f" {class_name} "

    def open_section(self):
        self.base_component_element(BaseElement).click()

    def collapse_section(self):
        self.get_child_element(BaseElement, By.XPATH, self.div_header).click()

    def add_new_group(self, first_question, answer):
        try:
            self.get_child_element(BaseElement, By.XPATH,
                                   self.btn_add_pair).click()
        except NoSuchElementException:
            pass
        except ElementNotVisibleException:
            pass
        self.get_child_element(
            BaseElement, By.XPATH,
            self.input_question_of_new_group).send_keys(first_question)
        self.get_child_element(
            BaseElement, By.XPATH,
            self.input_answer_of_new_group).send_keys(answer)
        self.get_child_element(BaseElement, By.TAG_NAME,
                               self.tfoot_tag_name).click()
        # time.sleep(1)

    def add_similar_question(self, answer, similar_question):
        row = self.find_row_element(answer=answer)
        btn_locator = ".//*[contains(@id,'add-similar-question')]/preceding-sibling::span"
        input_locator = ".//div[@placeholder='Type similar question']"
        # Find button add similar question
        btn_add_similar_question = self.get_child_element_if_exist(
            locator_type=By.XPATH,
            locator_value=btn_locator,
            parent_element=row)
        # Click on button add similar question if it exist
        (btn_add_similar_question
         is not None) and btn_add_similar_question.click()
        # Enter similar question
        row.find_element_by_xpath(input_locator).send_keys(similar_question)
        row.find_element_by_xpath(input_locator).send_keys(Keys.ENTER)

    def get_all_manual_faq(self) -> [dict]:
        result = []
        for row in self.find_all_row_element():
            questions = self.__get_all_similar_question_in_row(row)
            if len(questions) > 0:
                answer = row.find_element_by_xpath(
                    ".//div[@placeholder='Type an answer']").text
                result.append({"questions": questions, "answer": answer})
        return result

    def get_list_similar_question(self, answer):
        row = self.find_row_element(answer=answer)
        return self.__get_all_similar_question_in_row(row)

    def __get_all_similar_question_in_row(self, row: WebElement):
        result = []
        locator = "./td[1]/div[1]//span[@draggable]"
        similar_questions = row.find_elements_by_xpath(locator)
        for question in similar_questions:
            result.append(question.text)
        return result

    def find_row_element(self, answer=None, question=None) -> WebElement:
        if answer is not None:
            return self.get_child_element(
                BaseElement, By.XPATH, self.row_contains_answer.format(answer))
        elif question is not None:
            return self.get_child_element(
                BaseElement, By.XPATH,
                self.row_contains_question.format(question))
        else:
            raise Exception("Missing both answer and question")

    def find_all_row_element(self) -> List[WebElement]:
        return self.get_list_child_element(BaseElement, By.XPATH,
                                           ".//tbody//tr")
class FaqKnowledgeDataTableComponent(BaseComponent):
    def __init__(self):
        BaseComponent.__init__(
            self, By.XPATH,
            f"//div[contains(@class,'knowledge-styles') and contains(@class,'accordion')]"
        )
        self.__manual_faq_section = SectionWithGroupFAQ('Manual Q&A')

    base_locator = "//div[contains(@class,'knowledge-styles') and contains(@class,'accordion')"
    lbl_knowledge_title = ".//div[contains(@class,'title')]"
    btn_add_pair = ".//*[@id='add-pair-button-1']"

    base_elements = ElementFactory.get_list_element(by=By.XPATH,
                                                    locator=base_locator,
                                                    element_cls=BaseElement)

    @staticmethod
    def get_table_component_with_group_faqs(section_name):
        return SectionWithGroupFAQ(section_name)

    @staticmethod
    def get_table_component_with_pair_faqs(section_name):
        return SectionWithPairFAQ(section_name)

    @staticmethod
    def get_number_of_section():
        return len(FaqKnowledgeDataTableComponent.base_elements)

    def get_list_knowledge_title(self) -> List['str']:
        list_knowledge_title = []
        for element in self.get_list_child_element_in_list_component(
                BaseElement, By.XPATH, self.lbl_knowledge_title):
            list_knowledge_title.append(element.get_attribute("innerText"))
        return list_knowledge_title

    def input_new_manual_question_pair(self, question: str, answer: str):
        self.__manual_faq_section.add_new_group(question, answer)

    def modify_question_pair_at_index(self, index, question, answer):
        # TODO(namndoan): Update this when question field become editable
        pass

    def click_on_data_table_with_faq_url(self, faq_url):
        section_for_faq_url = SectionWithGroupFAQ(faq_url)
        section_for_faq_url.open_section()

    def get_all_question_pair_data_in_table(self):
        self.__manual_faq_section.wait_for_component_visible()
        return self.__manual_faq_section.get_all_manual_faq()

    def get_all_faq_data_in_table_with_faq_url(self, faq_url):
        section_for_faq_url = SectionWithGroupFAQ(faq_url)
        section_for_faq_url.wait_for_component_visible()
        # Open the section if it is not active
        if not section_for_faq_url.is_active_section():
            section_for_faq_url.open_section()
        return section_for_faq_url.get_all_manual_faq()

    def wait_for_manual_faq_section_visible(self):
        return self.__manual_faq_section.wait_for_component_visible()

    def get_number_of_manual_pair(self) -> str:
        return self.__manual_faq_section.get_section_info()["length"]
Ejemplo n.º 5
0
class ClientSimulator(BaseComponent):
    txt_feedback_title_locator = "//*[contains(@class, 'feedbackContainer')]/div[contains(@class, 'title')]"

    ico_open_bot = ElementFactory.get_element_until(
        by=By.XPATH,
        locator="//div[contains(@class, 'minimizedBoxContainer')]",
        wait_type=EC.visibility_of_element_located,
        element_cls=BaseElement
    )

    chat_box = ElementFactory.get_element_until(
        by=By.XPATH,
        locator="//div[contains(@class, 'chatboxContainer')]",
        wait_type=EC.visibility_of_element_located,
        element_cls=BaseElement
    )

    ico_close_bot = ElementFactory.get_element_until(
        by=By.XPATH,
        locator="//div[contains(@class, 'chatboxContainer')]//div[contains(@class, 'minimizeIcon')]",
        wait_type=EC.visibility_of_element_located,
        element_cls=BaseElement
    )

    txb_message = ElementFactory.get_element_until(
        by=By.XPATH,
        locator="//div[contains(@class, 'chatboxContainer')]//textarea",
        wait_type=EC.visibility_of_element_located,
        element_cls=BaseElement
    )

    list_txt_response = ElementFactory.get_list_element(
        by=By.XPATH,
        locator="//div[contains(@class,'messageContainerLeft')]//div[contains(@class,'messageTextLeft')]",
        element_cls=BaseElement
    )

    ifr_sample_app_chatbox = ElementFactory.get_element_until(
        by=By.CSS_SELECTOR,
        locator="#sample_app-minimized-box-frame",
        element_cls=BaseElement,
        wait_type=EC.visibility_of_element_located
    )

    ifr_chat_box = ElementFactory.get_element_until(
        by=By.ID, locator="sample_app-chatbox-frame",
        wait_type=EC.visibility_of_element_located,
        element_cls=BaseElement
    )

    txt_feedback_title = ElementFactory.get_element_until(
        by=By.XPATH, locator=txt_feedback_title_locator,
        wait_type=EC.visibility_of_element_located,
        element_cls=BaseElement
    )

    list_feedback_icon = ElementFactory.get_list_element(
        by=By.XPATH,
        locator="//*[contains(@class, 'feedbackContainer')]/div[contains(@class, 'ratingIconsContainer')]/*",
        element_cls=BaseElement
    )

    txt_latest_response = ElementFactory.get_element_until(
        by=By.XPATH,
        locator="(//*[contains(@class, 'styles__messageTextRight')])[last()]"
                "/../../../following-sibling::div[1]//*[contains(@class, 'styles__messageTextLeft')]",
        wait_type=EC.visibility_of_element_located,
        element_cls=BaseElement
    )

    btn_send_msg = ElementFactory.get_element_until(
        by=By.XPATH,
        locator="//div[contains(@class, 'chatboxContainer')]//textarea/../../following-sibling::button",
        wait_type=EC.visibility_of_element_located,
        element_cls=BaseElement
    )

    def __init__(self):
        BaseComponent.__init__(self, By.ID, "sample_app-chatbox")

    def open_chat_box(self):
        self.click_on_chatbot_icon()

    def close_chat_box(self):
        self.click_on_chatbot_icon()

    def click_on_chatbot_icon(self):
        self.driver.core_driver.switch_to.frame(self.ifr_sample_app_chatbox.get_wrapper_element)
        self.ico_open_bot.click()
        self.driver.core_driver.switch_to.parent_frame()

    def is_open(self):
        try:
            is_open = self.ifr_chat_box.is_displayed()
        except TimeoutException:
            is_open = False
        return is_open

    def send_message(self, message):
        if not self.is_open():
            self.open_chat_box()
        self._switch_to_chat_frame()
        self.txb_message.send_keys(message)
        self.btn_send_msg.click()
        self._switch_to_parent_frame()

    def get_responses(self):
        self._switch_to_chat_frame()
        responses = list(map(lambda elem: elem.get_element_attribute("innerText"), self.list_txt_response))
        self._switch_to_parent_frame()
        return responses

    def create_stub_messages(self, message, quantity=1):
        self.open_chat_box()
        self._switch_to_chat_frame()
        for i in range(quantity):
            self.txb_message.send_keys(message + " " + str(i))
            self.btn_send_msg.click()
            self.wait_for_response()
        self._switch_to_parent_frame()

    def wait_for_feedback_returned(self):
        self._switch_to_chat_frame()
        try:
            is_visible = self.txt_feedback_title.is_displayed()
        except TimeoutException:
            is_visible = False
        self._switch_to_parent_frame()
        return is_visible

    def wait_for_response(self):
        # Trigger wait method after each message is sent by calling the element
        return self.txt_latest_response

    def get_feedback_title(self):
        self._switch_to_chat_frame()
        text = self.txt_feedback_title.get_element_text()
        self._switch_to_parent_frame()
        return text

    def get_list_feedback_text(self):
        feedback_text = []
        self._switch_to_chat_frame()
        for element in self.list_feedback_icon:
            action = ActionChains(self.driver.core_driver).move_to_element(element.get_wrapper_element)
            action.perform()
            # Relocated element due to change in DOM
            ele = self.driver.core_driver.find_element_by_xpath(self.txt_feedback_title_locator)
            feedback_text.append(ele.text)
        self._switch_to_parent_frame()
        return feedback_text

    def _switch_to_chat_frame(self):
        self.driver.core_driver.switch_to.frame(self.ifr_chat_box.get_wrapper_element)

    def _switch_to_parent_frame(self):
        self.driver.core_driver.switch_to.parent_frame()

    def open_wait_close(self):
        pass

    def get_bot_avatar_source(self):
        self._switch_to_chat_frame()
        result = self.driver.core_driver.find_element_by_xpath("//img").get_attribute("src")
        self._switch_to_parent_frame()
        return result