class ShareLinkModal: JOIN_LINK_STARTS_WITH = "https://accounts.labs.livechatinc.com/join/" JOIN_LINK = (By.XPATH, "//input[@readonly and @type='text']") COPY_LINK = (By.XPATH, xpath_to_text("Copy link", tag="button")) GENERATE_NEW_LINK = (By.XPATH, xpath_to_text("Generate a new one")) CLOSE_MODAL = (By.XPATH, "//*[@class='modal-portal-container']//button[@title='Close modal']") def __init__(self, driver): self.driver = driver def get_join_link(self): for i in range(6): join_link_obj = self.driver.wait_for_visible(self.JOIN_LINK) join_link = join_link_obj.get_attribute("value") if self.JOIN_LINK_STARTS_WITH not in join_link: sleep(0.5) continue else: return join_link else: raise AssertionError("Join link not available") def click_generate_new_link(self): self.driver.click_with_timeout(self.GENERATE_NEW_LINK) def close_modal(self): self.driver.click_with_timeout(self.CLOSE_MODAL)
class DeleteModal: ACCEPT_DELETE = (By.XPATH, xpath_to_text("Delete", exact_match=True)) def __init__(self, driver): self.driver = driver def accept_deletion(self): self.driver.click_with_timeout(self.ACCEPT_DELETE)
class InstallCodePage: SKIP = (By.XPATH, xpath_to_text("I'll do it later →", exact_match=True)) def __init__(self, driver): self.driver = driver def skip_instalation(self): self.driver.click_with_timeout(self.SKIP)
class InvitationsSentModal: DONE = (By.XPATH, xpath_to_text("Done", exact_match=True, tag="button")) def __init__(self, driver): self.driver = driver def click_done(self): self.driver.click_with_timeout(self.DONE)
class AgentManagement: ADD = (By.XPATH, xpath_to_text("Add", tag="button", exact_match=True)) INVITE_AGENTS_DIRECT = (By.XPATH, xpath_to_text("Invite Agents", tag="td/span", exact_match=True)) INACTIVE_GROUPS_SECTION = ( By.XPATH, "//*[@id='agents-new']//a[@href='/agents/groups']") ACTIVE_GROUPS_SECTION = ( By.XPATH, "//*[@id='groups-new']//a[@href='/agents/groups']") def __init__(self, driver): self.driver = driver def click_add_button(self): self.driver.click_with_timeout(self.ADD) def click_invite_agents_direct(self): self.driver.click_with_timeout(self.INVITE_AGENTS_DIRECT) def go_to_groups_section(self): self.driver.click_with_timeout(self.INACTIVE_GROUPS_SECTION)
class AddContext(agent_management.AgentManagement): INVITE_AGENTS_VIA_ADD = (By.XPATH, xpath_to_text("Invite Agents", exact_match=True)) IMPORT_GSUITE = (By.XPATH, xpath_to_text("Import G Suite users", tag="button")) SHARE_INVITE = (By.XPATH, xpath_to_text("Share invite link", tag="button", exact_match=True)) ADD_BOT = (By.XPATH, xpath_to_text("Add a bot", tag="a", exact_match=True)) CREATE_GROUP = (By.XPATH, xpath_to_text("Create a group", tag="a", exact_match=True)) def click_invite_agents_on_add_section(self): self.driver.click_with_timeout(self.INVITE_AGENTS_VIA_ADD) def click_import_gsuite_users(self): self.driver.click_with_timeout(self.IMPORT_GSUITE) def click_share_invite_link(self): self.driver.click_with_timeout(self.SHARE_INVITE) def click_add_bot(self): self.driver.click_with_timeout(self.ADD_BOT) def click_create_a_group(self): self.driver.click_with_timeout(self.CREATE_GROUP)
class Edit: DELETE_AGENT = (By.XPATH, xpath_to_text("Delete agent.", tag="button")) AGENT_PERMISSION = ( By.XPATH, "//label[.//@type='radio' and .//@name='permission' and .//@value='normal']" ) ADMIN_PERMISSION = ( By.XPATH, "//label[.//@type='radio' and .//@name='permission' and .//@value='viceowner']" ) ACCEPT_CHANGES = (By.XPATH, xpath_to_text("Save changes", exact_match=True, tag="button")) def __init__(self, driver): self.driver = driver def click_delete_agent(self): self.driver.click_with_timeout_and_scroll(self.DELETE_AGENT) def set_agent_permission(self): self.driver.click_with_timeout_and_scroll(self.AGENT_PERMISSION) def set_admin_permission(self): self.driver.click_with_timeout_and_scroll(self.ADMIN_PERMISSION) def accept_changes(self): self.driver.click_with_timeout(self.ACCEPT_CHANGES) @staticmethod def __get_formatted_xpath_locator(xpath, formatter): """ Uses xpath tuple with placeholder to be filled in by formatter """ return tuple((xpath[0], xpath[1].format(formatter)))
class InviteModal: INVITE_ANOTHER = (By.XPATH, xpath_to_text("Invite another")) SEND_INVITATIONS = (By.XPATH, "//button[@type='submit']") INVALID_EMAIL = (By.XPATH, "//*[@class='field-error'][contains(text(), 'Please provide a valid email address')])") ROLE_INPUT_BOX = (By.XPATH, "//input[@name='select-box-input']") SELECT_ROLE_BOXES = (By.XPATH, "//div[@class='selected-item']") SELECT_ROLE_OPTIONS__FORMAT = (By.XPATH, "//li[./div/span[text()='{}']]") SELECT_GROUP_OPTIONS__FORMAT = (By.XPATH, "//li[./div/span[text()='{}']]") INPUT_GROUP = (By.XPATH, "//input[contains(@name, 'multiselectbox')]") EMAIL_BOX__FORMAT = (By.ID, "email-{}") def __init__(self, driver): self.driver = driver def assure_number_of_invite_fields(self, num): base_num_of_fields = 3 if num > base_num_of_fields: for i in range(num-3): self.click_add_another_invite() elif num < base_num_of_fields: for i in range(3-num): pass def click_add_another_invite(self): self.driver.click_with_timeout(self.INVITE_ANOTHER) def click_send_invitations(self): self.driver.click_with_timeout(self.SEND_INVITATIONS) def fill_email_box(self, email_box_num, email): """ :param email_box_num: starts with 0 :param email: user email """ self.driver.write_to_element(self.__get_email_box_locator(email_box_num), email) def click_roles_box(self, role_box_num): role_boxes = self.driver.wait_for_multiple_present(self.SELECT_ROLE_BOXES, timeout=5) role_boxes[role_box_num].click() def select_role(self, role, role_box_num): selectables_of_this_role = self.driver.wait_for_multiple_present(self.__get_select_role_locator(role)) selectables_of_this_role[role_box_num].click() def click_groups_box(self, group_box_num): group_inputs = self.driver.wait_for_multiple_present(self.INPUT_GROUP) group_inputs[group_box_num].click() # its the same as select_role def select_group(self, group, group_box_num): selectables_of_this_group = self.driver.wait_for_multiple_present(self.__get_select_role_locator(group)) selectables_of_this_group[group_box_num].click() def __get_select_role_locator(self, role): f""" Fills in {self.SELECT_ROLE_OPTIONS__FORMAT} with role so it returns locator :param role: string of a role to choose :return: locator of specific email box """ return self.__get_formatted_xpath_locator(self.SELECT_ROLE_OPTIONS__FORMAT, role) def __get_email_box_locator(self, num): f""" Fills in {self.EMAIL_BOX__FORMAT} with number so it returns locator :param num: iterated from 0 :return: locator of specific email box """ return self.__get_formatted_xpath_locator(self.EMAIL_BOX__FORMAT, num) @staticmethod def __get_formatted_xpath_locator(xpath, formatter): """ Uses xpath tuple with placeholder to be filled in by formatter """ return tuple((xpath[0], xpath[1].format(formatter))) def wait_for_lagging_error_on_invalid_emails(self): """ Invalid email error is lagging behind automated script, so here we wait until it appears and disappears :return: """ try: self.driver.wait_for_visible(self.INVALID_EMAIL, timeout=2) except TimeoutException: self.driver.wait_for_invisible(self.INVALID_EMAIL, timeout=2)