class ForgotPasswordPage(BasePage): page_load_timeout = 10 change_password_timeout = 10 path_page = "/account/forgot_password" txb_email = ElementFactory.get_element_until( by=By.ID, locator="email-input", wait_type=visibility_of_element_located, element_cls=SeleniumElement) btn_send = ElementFactory.get_element_until( by=By.ID, locator="signin-button", wait_type=element_to_be_clickable, element_cls=SeleniumElement) lbl_error_message = ElementFactory.get_element_until( by=By.XPATH, locator="//*[@id='signin-button']/preceding-sibling::*", wait_type=visibility_of_element_located, element_cls=SeleniumElement) def open_forgot_password_page(self): self.open_page(self.path_page) def wait_for_forgot_password_page(self): self.wait_for_page(self.path_page, self.page_load_timeout) def submit_email(self, email): self.txb_email.clear_and_send_keys(email) self.btn_send.click()
class ChatBoxSimulator(BasePage): path_page = "/admin/setting_bot/appearance" btn_drop_down_list = ElementFactory.get_element_until( by=By.ID, locator="dropDownListBotTriggerButton", wait_type=EC.visibility_of_element_located, element_cls=BaseElement) txt_input_message = ElementFactory.get_element_until( by=By.ID, locator="inputmessage", wait_type=EC.visibility_of_element_located, element_cls=BaseElement) btn_send_message = ElementFactory.get_element_until( by=By.XPATH, locator="//textarea[contains(@id,'inputmessage')]" "/following-sibling::span[1]/*", wait_type=EC.visibility_of_element_located, element_cls=BaseElement) def open_configure_appearance_page(self): self.open_page(self.path_page) def send_message(self, message): self.txt_input_message.send_keys(message) self.txt_input_message.send_keys(Keys.RETURN) def get_result(self, messages): result = messages response = self.get_responses_list() for i in range(1, len(messages)): result[i].append(response[i][0]) return result def get_responses_list(self): responses_list = [] conversation = self.get_conversation() messages_data = json.loads(conversation)['chatbox'] for message in messages_data['messages']: if not message['isUser']: responses_list.append([message['data']]) return responses_list[0:] def get_conversation(self): storage = LocalStorage(self.driver) return storage.get('state') def clear_conversation(self): storage = LocalStorage(self.driver) storage.remove
class IntegrationPage(BasePage): path_page = "/admin/setting_bot/integration" txb_script = ElementFactory.get_element_until( by=By.XPATH, locator="//*[@id='copy-button']/../following-sibling::div", wait_type=EC.visibility_of_element_located, element_cls=BaseElement) def get_script(self): return self.txb_script.get_element_text() def open_integration_page(self): self.open_page(self.path_page)
class ResetPasswordPage(BasePage): page_load_timeout = 10 change_password_timeout = 10 path_page = "/account/reset_password" txb_new_password = ElementFactory.get_element_until( by=By.ID, locator="password-input", wait_type=visibility_of_element_located, element_cls=SeleniumElement) btn_change_password = ElementFactory.get_element_until( by=By.ID, locator="signin-button", wait_type=visibility_of_element_located, element_cls=SeleniumElement) lbl_error_message = ElementFactory.get_element_until( by=By.XPATH, locator="//*[@id='signin-button']/preceding-sibling::*", wait_type=visibility_of_element_located, element_cls=SeleniumElement) def open_reset_password_page(self, token): self.open_page(ResetPasswordPage.get_full_url_from_token(token)) def wait_for_forgot_password_page(self): self.txb_new_password def reset_password(self, new_password): self.txb_new_password.clear_and_send_keys(new_password) self.btn_change_password.click() @staticmethod def get_full_url_from_token(token): url_pattern = "{}/auth/recover_password?token={}" return url_pattern.format(Settings.BASE_URL, token)
class ChangePasswordPage(BasePage): page_load_timeout = 10 change_password_timeout = 10 path_page = "/admin/manage_account/change_password" txb_old_password = ElementFactory.get_element_until( by=By.ID, locator="old-password-input", wait_type=visibility_of_element_located, element_cls=SeleniumElement) txb_new_password = ElementFactory.get_element_until( by=By.ID, locator="new-password-input", wait_type=visibility_of_element_located, element_cls=SeleniumElement) txb_confirm_password = ElementFactory.get_element_until( by=By.ID, locator="confirm-new-password-input", wait_type=visibility_of_element_located, element_cls=SeleniumElement) btn_submit = ElementFactory.get_element_until( by=By.ID, locator="change-password-button", wait_type=visibility_of_element_located, element_cls=SeleniumElement) btn_cancel = ElementFactory.get_element_until( by=By.ID, locator="cancel-button", wait_type=visibility_of_element_located, element_cls=SeleniumElement) txt_error_message = ElementFactory.get_element_until( by=By.XPATH, locator="//button[@id='change-password-button']/../../span", wait_type=visibility_of_element_located, element_cls=SeleniumElement) txt_success_message = ElementFactory.get_element_until( by=By.XPATH, locator="//*[@id='return-dashboard-button']/../../span", wait_type=visibility_of_element_located, element_cls=SeleniumElement) btn_back_to_dashboard = ElementFactory.get_element_until( by=By.ID, locator="return-dashboard-button", wait_type=visibility_of_element_located, element_cls=SeleniumElement) def open_change_password_page(self): self.open_page(self.path_page) def wait_for_change_password_page(self): self.wait_for_page(self.path_page, self.page_load_timeout) def change_password(self, old_password, new_password, confirm_password=None): self.txb_old_password.clear_and_send_keys(old_password) self.txb_new_password.clear_and_send_keys(new_password) if confirm_password is not None: self.txb_confirm_password.clear_and_send_keys(confirm_password) else: self.txb_confirm_password.clear_and_send_keys(new_password) self.btn_submit.click() def get_error_message(self): return self.txt_error_message.get_element_text() def get_success_message(self): return self.txt_success_message.get_element_text() # TODO(namndoan): it may not work def wait_for_button_submit_disappear(self): return WebDriverWait( driver=self.driver, timeout=self.change_password_timeout ).until( staleness_of(self.btn_submit.get_wrapper_element), f"Button submit is still displayed after {self.change_password_timeout}s" ) def wait_for_button_back_to_dashboard_display(self): # Wait for button back to dashboard visible return self.btn_back_to_dashboard # Additional code for logging out div_user_options = ElementFactory.get_element_until( element_cls=SeleniumElement, by=By.ID, locator="user-options-dropdown", wait_type=visibility_of_element_located) btn_log_out = ElementFactory.get_element_until( element_cls=SeleniumElement, by=By.XPATH, locator= "//*[@id='user-options-dropdown']//div//span[text()='Sign-out']", wait_type=visibility_of_element_located) def log_out(self): self.div_user_options.click() self.btn_log_out.click()
class KnowledgePage(BasePage): def __init__(self): BasePage.__init__(self) self.__add_faq_url_component = AddFaqUrlComponent() self.__loader_component = LoaderComponent() self.__faq_knowledge_datatable_component = FaqKnowledgeDataTableComponent( ) timeout = 10 add_url_knowledge_timeout = 300 path_page = "/admin/setting_bot/knowledge" lbl_header_title = ElementFactory.get_element_until( by=By.CSS_SELECTOR, element_cls=BaseElement, locator="h2.header", wait_type=EC.visibility_of_element_located, time_out=120) btn_add_knowledge = ElementFactory.get_element_until( element_cls=ButtonElement, by=By.XPATH, locator="//div[contains(@class,'knowledge-styles') " "and @role='listbox']", wait_type=EC.element_to_be_clickable, time_out=30) btn_from_faq_url = ElementFactory.get_element_until( element_cls=ButtonElement, by=By.ID, locator="optionAddFAQUrl", wait_type=EC.element_to_be_clickable, time_out=30) btn_from_faq_manual_qa = ElementFactory.get_element_until( element_cls=ButtonElement, by=By.ID, locator="optionAddNewPairManually", wait_type=EC.element_to_be_clickable, time_out=30) btn_ok_add_faq_url = ElementFactory.get_element_until( element_cls=ButtonElement, by=By.ID, locator="submit-url-button", wait_type=EC.element_to_be_clickable, time_out=30) btn_cancel_add_faq_url = ElementFactory.get_element_until( element_cls=ButtonElement, by=By.ID, locator="cancel-process-button", wait_type=EC.element_to_be_clickable, time_out=30) txt_from_faq_url = ElementFactory.get_element_until( element_cls=InputElement, by=By.XPATH, locator="//div[contains(@class,'knowledge-styles')]" "//input[@placeholder='Enter a FAQ URL here']", wait_type=EC.element_to_be_clickable, time_out=30) def add_manual_faq_url(self, faq_url): self.__loader_component.wait_for_component_invisible() self.btn_add_knowledge.click() self.btn_from_faq_url.click() self.txt_from_faq_url.send_keys(faq_url) self.btn_ok_add_faq_url.click() def init_manual_question_pair_table(self): self.__loader_component.wait_for_component_invisible() self.btn_add_knowledge.click() self.btn_from_faq_manual_qa.click() self.__faq_knowledge_datatable_component.wait_for_manual_faq_section_visible( ) def add_question_answer_data(self, question, answer): self.__faq_knowledge_datatable_component.input_new_manual_question_pair( question, answer) def modify_question_answer_at_index(self, index, question, answer): self.__faq_knowledge_datatable_component.modify_question_pair_at_index( index, question, answer) def get_faq_url_data(self) -> List['str']: self.__add_faq_url_component.wait_for_component_remove() return self.__faq_knowledge_datatable_component.get_list_knowledge_title( ) def get_question_pair_data_in_gui(self): return self.__faq_knowledge_datatable_component.get_all_question_pair_data_in_table( ) def get_faq_url_data_in_gui(self, faq_url): self.__faq_knowledge_datatable_component.click_on_data_table_with_faq_url( faq_url) return self.__faq_knowledge_datatable_component.get_all_faq_data_in_table_with_faq_url( faq_url) # Work def wait_for_create_page(self, time_out=None): time_out = time_out if time_out is not None else self.timeout self.wait_for_page(self.path_page, time_out) self.lbl_header_title def wait_for_knowledge_section_visible(self, title): component = FaqKnowledgeDataTableComponent.get_table_component_with_group_faqs( title) component.wait_for_component_visible(self.add_url_knowledge_timeout) def open_knowledge_page(self): self.open_page(self.path_page)
class CreateBotPage(BasePage): timeout = 10 path_page = "/admin/manage_account/create_bot" txt_website_url = ElementFactory.get_element_until( by=By.ID, locator="website-input", wait_type=EC.visibility_of_element_located, element_cls=SeleniumElement) txt_bot_name = ElementFactory.get_element_until( by=By.ID, locator="chatbot-name-input", wait_type=EC.visibility_of_element_located, element_cls=SeleniumElement) btn_create_bot = ElementFactory.get_element_until( by=By.ID, locator="create-button", wait_type=EC.visibility_of_element_located, element_cls=SeleniumElement) lbl_error_message = ElementFactory.get_element( by=By.XPATH, locator="//button[@id='create-button']/../span", element_cls=SeleniumElement) # Should move to common page object txt_bottom_left_noti = ElementFactory.get_element( by=By.CSS_SELECTOR, locator="#root div.notifications-wrapper div.notification-message", element_cls=SeleniumElement) txt_header = ElementFactory.get_element_until( by=By.CSS_SELECTOR, locator="h2.header", wait_type=EC.visibility_of_element_located, element_cls=BaseElement) def __init__(self): self.__db_helper = DatabaseHelper(DatabaseType.MONGO_DB).database_query self.__loader_component = LoaderComponent() @property def txt_header_text(self): return "Create your virtual assistant" def get_header_text(self) -> str: return self.txt_header.get_element_text() def open_create_page(self): self.open_page(self.path_page) def create_bot_with_data(self, bot_name, website_url): self.input_bot_info_with_data(bot_name, website_url) self.click_create_bot_button() self.__loader_component.wait_for_component_invisible(60) def input_bot_info_with_data(self, bot_name, website_url): self.txt_bot_name.send_keys(bot_name) self.txt_website_url.send_keys(website_url) def click_create_bot_button(self): self.btn_create_bot.click() def wait_for_create_page(self): self.wait_for_page(self.path_page, self.timeout) def get_bot_data_via_user_email(self, user_email): return self.__db_helper.get_item_in_collection( "Bot", {"creators.0.email": user_email}) def get_bot_data_via_user_email_and_bot_name(self, user_email, bot_name): return self.__db_helper.get_item_in_collection("Bot", { "creators.0.email": user_email, "name": bot_name }) def get_list_question_via_bot_id(self, bot_id): return self.__db_helper.get_list_item_in_collection( "Qna", {"botId": bot_id})
class AppearancePage(BasePage): timeout = 10 update_info_timeout = 1 path_page = "/admin/setting_bot/appearance" lbl_header_title = ElementFactory.get_element_until(by=By.CSS_SELECTOR, element_cls=SeleniumElement, locator="h2.header", wait_type=EC.visibility_of_element_located, time_out=120 ) txb_title = ElementFactory.get_element_until(by=By.ID, locator="titleField", wait_type=EC.visibility_of_element_located, element_cls=SeleniumElement) txb_bot_name = ElementFactory.get_element_until(by=By.ID, locator="nameField", wait_type=EC.visibility_of_element_located, element_cls=SeleniumElement) img_avatar = ElementFactory.get_element_until(by=By.XPATH, locator="//*[@id='nameField']/../../..//img", wait_type=EC.visibility_of_element_located, element_cls=SeleniumElement) input_ava = ElementFactory.get_element_until(by=By.XPATH, locator="//input[@accept]", wait_type=EC.visibility_of_element_located, element_cls=SeleniumElement) lbl_error_message_of_upload_avatar = ElementFactory.get_element_until(by=By.XPATH, locator="//input[@accept]/../../span", wait_type=EC.visibility_of_element_located, element_cls=SeleniumElement) btn_cancel_upload_avatar = ElementFactory.get_element_until(by=By.XPATH, locator="//button[@name='cancelButton']", wait_type=EC.visibility_of_element_located, element_cls=SeleniumElement ) btn_save_uploaded_avatar = ElementFactory.get_element_until(by=By.XPATH, locator="//button[@name='saveButton']", wait_type=EC.visibility_of_element_located, element_cls=SeleniumElement) def get_header_title_text(self): return self.lbl_header_title.get_element_text() def get_expected_title(self, bot_name): # Title is converted to uppercase return "{}'S APPEARANCE".format(bot_name.upper()) def open_appearance_page(self): self.open_page(self.path_page) def wait_for_appearance_page(self, time_out=None): time_out = time_out if time_out is not None else self.timeout self.wait_for_page(self.path_page, time_out) def change_bot_title(self, new_title): # Work around instead of clear_and_send_keys due to element is not user-editable self.txb_title.click() self.txb_title.clear_and_send_keys(new_title) self.lbl_header_title.click() time.sleep(self.update_info_timeout) def change_bot_name(self, new_name): self.txb_bot_name.click() self.txb_bot_name.clear_and_send_keys(new_name) self.lbl_header_title.click() time.sleep(self.update_info_timeout) def update_avatar(self, file_path): self.img_avatar.click() self.input_ava.send_keys(file_path) self.btn_save_uploaded_avatar.click()
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