pages/desktop/frontend/users.py (713 lines of code) (raw):
import os
from pathlib import Path
from pypom import Region
from selenium.webdriver.common.by import By
from selenium.common.exceptions import StaleElementReferenceException
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from pages.desktop.base import Base
from pages.desktop.frontend.home import Home
from pages.desktop.frontend.reviews import Reviews
from pages.desktop.frontend.search import Search
class User(Base):
URL_TEMPLATE = "/users/edit"
_display_name_locator = (By.CLASS_NAME, "UserProfile-name")
def wait_for_page_to_load(self):
"""Waits for various page components to be loaded"""
self.wait.until(
EC.invisibility_of_element_located((By.CLASS_NAME, "LoadingText"))
)
return self
def wait_for_user_to_load(self):
WebDriverWait(
self.driver, 20, ignored_exceptions=StaleElementReferenceException
).until(lambda _: self.is_element_displayed(*self._display_name_locator))
return self
@property
def user_display_name(self):
self.wait.until(EC.visibility_of_element_located(self._display_name_locator))
return self.find_element(*self._display_name_locator)
@property
def view(self):
return self.ViewProfile(self)
@property
def edit(self):
return self.EditProfile(self)
@property
def minimal(self):
return self.MinimalProfileDetails(self)
class MinimalProfileDetails(Region):
_profile_name_selector = (By.CSS_SELECTOR, ".UserProfile-name")
_user_profile_since_selector = (By.CSS_SELECTOR, ".UserProfile-user-since")
_report_abuse_button_selector = (By.CSS_SELECTOR, ".ReportUserAbuse-show-more")
@property
def profile_name(self):
self.wait.until(
EC.visibility_of_element_located(self._profile_name_selector)
)
return self.find_element(*self._profile_name_selector)
@property
def user_profile_since(self):
self.wait.until(
EC.visibility_of_element_located(self._user_profile_since_selector)
)
return self.find_element(*self._user_profile_since_selector)
@property
def report_abuse_button(self):
self.wait.until(
EC.visibility_of_element_located(self._report_abuse_button_selector)
)
return self.find_element(*self._report_abuse_button_selector)
class ViewProfile(Region):
_user_icon_placeholder_locator = (By.CSS_SELECTOR, ".Icon-anonymous-user")
_user_profile_image_locator = (By.CSS_SELECTOR, ".UserAvatar-image")
_user_developer_role_locator = (By.CSS_SELECTOR, ".UserProfile-developer")
_user_developer_role_icon_locator = (By.CSS_SELECTOR, ".Icon-developer")
_user_artist_role_locator = (By.CSS_SELECTOR, ".UserProfile-artist")
_user_artist_role_icon_locator = (By.CSS_SELECTOR, ".Icon-artist")
_user_homepage_locator = (By.CSS_SELECTOR, ".UserProfile-homepage a")
_user_location_locator = (By.CSS_SELECTOR, ".UserProfile-location")
_user_occupation_locator = (By.CSS_SELECTOR, ".UserProfile-occupation")
_user_creation_date_locator = (By.CSS_SELECTOR, ".UserProfile-user-since")
_user_addons_count_locator = (By.CSS_SELECTOR, ".UserProfile-number-of-addons")
_user_addon_average_rating_locator = (
By.CSS_SELECTOR,
".UserProfile-rating-average",
)
_user_biography_locator = (By.CSS_SELECTOR, ".UserProfile-biography")
_user_profile_edit_link_locator = (By.CSS_SELECTOR, ".UserProfile-edit-link")
_user_extensions_card_locator = (By.CSS_SELECTOR, ".AddonsCard--vertical")
_user_extensions_card_header_locator = (
By.CSS_SELECTOR,
".AddonsCard--vertical .Card-header-text",
)
_user_extensions_results_locator = (
By.CSS_SELECTOR,
".AddonsCard--vertical .SearchResult",
)
_user_themes_card_locator = (By.CSS_SELECTOR, ".AddonsByAuthorsCard--theme")
_user_themes_card_header_locator = (
By.CSS_SELECTOR,
".AddonsByAuthorsCard--theme .Card-header-text",
)
_user_themes_results_locator = (By.CLASS_NAME, "SearchResult--theme")
_user_reviews_card_locator = (By.CSS_SELECTOR, ".UserProfile-reviews")
_extensions_pagination_locator = (
By.CSS_SELECTOR,
".AddonsCard--vertical .Paginate",
)
_extensions_next_page_locator = (
By.CSS_SELECTOR,
".AddonsCard--vertical .Paginate-item--next",
)
_extensions_page_number_locator = (
By.CSS_SELECTOR,
".AddonsCard--vertical .Paginate-page-number",
)
_themes_pagination_locator = (
By.CSS_SELECTOR,
".AddonsByAuthorsCard--theme .Paginate",
)
_themes_next_page_locator = (
By.CSS_SELECTOR,
".AddonsByAuthorsCard--theme .Paginate-item--next",
)
_themes_page_number_locator = (
By.CSS_SELECTOR,
".AddonsByAuthorsCard--theme .Paginate-page-number",
)
_user_review_list_locator = (By.CSS_SELECTOR, ".AddonReviewCard-viewOnly")
_user_abuse_report_button_locator = (
By.CSS_SELECTOR,
".ReportUserAbuse-show-more",
)
_abuse_report_form_header_locator = (By.CSS_SELECTOR, ".Card-header-text")
_abuse_report_form_help_text = (
By.CSS_SELECTOR,
"section.Card:nth-child(2) > div:nth-child(2) > h3",
)
_abuse_report_form_additional_help_text = (
By.ID,
"feedbackText-help",
)
_abuse_report_textarea_locator = (
By.CSS_SELECTOR,
".FeedbackForm--Card",
)
_abuse_report_cancel_button_locator = (
By.CSS_SELECTOR,
".DismissibleTextForm-dismiss",
)
_abuse_report_submit_disabled_button_locator = (
By.CSS_SELECTOR,
".FeedbackForm-button.Button--disabled",
)
_abuse_report_form_provide_more_details = (
By.ID, "feedbackText"
)
_abuse_report_submit_button_locator = (
By.CSS_SELECTOR,
".Button",
)
_abuse_report_confirm_message_locator = (
By.CSS_SELECTOR,
"p.FeedbackForm-success-first-paragraph",
)
_feedback_category_spam_locator = (
By.ID,
"feedbackCategoryfeedback_spam"
)
def click_category_spam(self):
self.wait.until(
EC.visibility_of_element_located(self._feedback_category_spam_locator)
)
self.find_element(*self._feedback_category_spam_locator).click()
return self.find_element(*self._feedback_category_spam_locator)
@property
def user_profile_icon_placeholder(self):
self.wait.until(
EC.visibility_of_element_located(self._user_icon_placeholder_locator)
)
return self.find_element(*self._user_icon_placeholder_locator)
@property
def user_profile_icon(self):
return self.find_element(*self._user_profile_image_locator)
@property
def icon_source(self):
return self.user_profile_icon.get_attribute("src")
@property
def developer_role(self):
self.wait.until(
EC.visibility_of_element_located(self._user_developer_role_locator)
)
return self.find_element(*self._user_developer_role_locator)
@property
def developer_role_icon(self):
self.wait.until(
EC.visibility_of_element_located(self._user_developer_role_icon_locator)
)
return self.find_element(*self._user_developer_role_icon_locator)
@property
def artist_role(self):
self.wait.until(
EC.visibility_of_element_located(self._user_artist_role_locator)
)
return self.find_element(*self._user_artist_role_locator)
@property
def artist_role_icon(self):
self.wait.until(
EC.visibility_of_element_located(self._user_artist_role_icon_locator)
)
return self.find_element(*self._user_artist_role_icon_locator)
@property
def user_homepage(self):
self.wait.until(
EC.visibility_of_element_located(self._user_homepage_locator)
)
return self.find_element(*self._user_homepage_locator).get_attribute("href")
@property
def user_location(self):
self.wait.until(
EC.visibility_of_element_located(self._user_location_locator)
)
return self.find_element(*self._user_location_locator).text
@property
def user_occupation(self):
self.wait.until(
EC.visibility_of_element_located(self._user_occupation_locator)
)
return self.find_element(*self._user_occupation_locator).text
@property
def user_profile_creation_date(self):
self.wait.until(
EC.visibility_of_element_located(self._user_creation_date_locator)
)
return self.find_element(*self._user_creation_date_locator)
@property
def user_addons_number(self):
self.wait.until(
EC.visibility_of_element_located(self._user_addons_count_locator)
)
return self.find_element(*self._user_addons_count_locator)
@property
def user_addons_average_rating(self):
self.wait.until(
EC.visibility_of_element_located(
self._user_addon_average_rating_locator
)
)
return self.find_element(*self._user_addon_average_rating_locator)
@property
def user_biography(self):
return self.find_element(*self._user_biography_locator).text
@property
def edit_profile_button(self):
self.wait.until(
EC.visibility_of_element_located(self._user_profile_edit_link_locator)
)
return self.find_element(*self._user_profile_edit_link_locator)
def click_edit_profile_button(self):
self.wait.until(
EC.element_to_be_clickable(self._user_profile_edit_link_locator)
)
self.find_element(*self._user_profile_edit_link_locator).click()
return User(self.driver, self.page.base_url).wait_for_page_to_load()
@property
def user_extensions(self):
self.wait.until(
EC.visibility_of_element_located(self._user_extensions_card_locator)
)
self.find_element(*self._user_extensions_card_locator)
return Search(self.driver, self.page.base_url).wait_for_page_to_load()
@property
def user_extensions_card_header(self):
self.wait.until(
EC.visibility_of_element_located(
self._user_extensions_card_header_locator
)
)
return self.find_element(*self._user_extensions_card_header_locator).text
@property
def user_extensions_results(self):
self.wait.until(
EC.visibility_of_element_located(self._user_extensions_results_locator)
)
items = self.find_elements(*self._user_extensions_results_locator)
return [
Search(
self.driver, self.page.base_url
).SearchResultList.ResultListItems(self, el)
for el in items
]
@property
def user_themes(self):
self.wait.until(
EC.visibility_of_element_located(self._user_themes_card_locator)
)
self.find_element(*self._user_themes_card_locator)
return Search(self.driver, self.page.base_url).wait_for_page_to_load()
@property
def user_themes_card_header(self):
self.wait.until(
EC.visibility_of_element_located(self._user_themes_card_header_locator)
)
return self.find_element(*self._user_themes_card_header_locator).text
@property
def user_themes_results(self):
self.wait.until(
EC.visibility_of_element_located(self._user_themes_results_locator)
)
items = self.find_elements(*self._user_themes_results_locator)
return [
Search(
self.driver, self.page.base_url
).SearchResultList.ResultListItems(self, el)
for el in items
]
@property
def extensions_pagination(self):
self.wait.until(
EC.visibility_of_element_located(self._extensions_pagination_locator)
)
return self.find_element(*self._extensions_pagination_locator)
def extensions_next_page(self):
self.wait.until(
EC.element_to_be_clickable(self._extensions_next_page_locator)
)
self.find_element(*self._extensions_next_page_locator).click()
return User(self.driver, self.page.base_url).wait_for_page_to_load()
@property
def extensions_page_number(self):
self.wait.until(
EC.visibility_of_element_located(self._extensions_page_number_locator)
)
return self.find_element(*self._extensions_page_number_locator).text
@property
def themes_pagination(self):
return self.find_element(*self._themes_pagination_locator)
def themes_next_page(self):
self.wait.until(EC.element_to_be_clickable(self._themes_next_page_locator))
self.find_element(*self._themes_next_page_locator).click()
return User(self.driver, self.page.base_url).wait_for_page_to_load()
@property
def themes_page_number(self):
self.wait.until(
EC.visibility_of_element_located(self._themes_page_number_locator)
)
return self.find_element(*self._themes_page_number_locator).text
def user_reviews_section_loaded(self):
self.wait.until(
EC.visibility_of_element_located(self._user_reviews_card_locator)
)
@property
def user_review_items(self):
items = self.find_elements(*self._user_review_list_locator)
reviews = Reviews(self.driver, self.page.base_url).wait_for_page_to_load()
return [reviews.UserReview(self, el) for el in items]
@property
def abuse_report_form_provide_more_details(self):
return self.find_element(*self._abuse_report_form_provide_more_details)
def click_user_abuse_report(self):
self.wait.until(
EC.element_to_be_clickable(self._user_abuse_report_button_locator)
)
self.find_element(*self._user_abuse_report_button_locator).click()
self.wait.until(
EC.element_to_be_clickable(self._abuse_report_textarea_locator)
)
@property
def abuse_report_form_header(self):
self.wait.until(
EC.visibility_of_element_located(self._abuse_report_form_header_locator)
)
return self.find_element(*self._abuse_report_form_header_locator).text
@property
def abuse_report_form_help_text(self):
self.wait.until(
EC.visibility_of_element_located(self._abuse_report_form_help_text)
)
return self.find_element(*self._abuse_report_form_help_text).text
@property
def abuse_report_form_additional_help_text(self):
self.wait.until(
EC.visibility_of_element_located(
self._abuse_report_form_additional_help_text
)
)
return self.find_element(*self._abuse_report_form_additional_help_text).text
def user_abuse_report_input_text(self, value):
self.wait.until(
EC.visibility_of_element_located(self._abuse_report_textarea_locator)
)
self.find_element(*self._abuse_report_textarea_locator).send_keys(value)
def cancel_abuse_report_form(self):
self.wait.until(
EC.element_to_be_clickable(self._abuse_report_cancel_button_locator)
)
self.find_element(*self._abuse_report_cancel_button_locator).click()
self.wait.until(
EC.element_to_be_clickable(self._user_abuse_report_button_locator)
)
@property
def abuse_report_submit_disabled(self):
self.wait.until(
EC.visibility_of_element_located(
self._abuse_report_submit_disabled_button_locator
)
)
return self.find_element(*self._abuse_report_submit_disabled_button_locator)
def submit_user_abuse_report(self):
self.wait.until(
EC.element_to_be_clickable(self._abuse_report_submit_button_locator)
)
self.find_element(*self._abuse_report_submit_button_locator).click()
self.wait.until(
EC.invisibility_of_element_located(
self._abuse_report_submit_button_locator
)
)
@property
def user_abuse_confirmation_message(self):
self.wait.until(
EC.visibility_of_element_located(
self._abuse_report_confirm_message_locator
)
)
return self.find_element(*self._abuse_report_confirm_message_locator).text
class EditProfile(Region):
_view_profile_link_locator = (By.CSS_SELECTOR, ".UserProfileEdit-user-links a")
_user_email_locator = (By.CSS_SELECTOR, ".UserProfileEdit-email")
_user_email_help_text_locator = (
By.CSS_SELECTOR,
".UserProfileEdit-email--help",
)
_user_email_help_link_locator = (
By.CSS_SELECTOR,
".UserProfileEdit-email--help a",
)
_fxa_account_link_locator = (
By.CSS_SELECTOR,
".UserProfileEdit-manage-account-link",
)
_edit_display_name_locator = (By.CSS_SELECTOR, ".UserProfileEdit-displayName")
_edit_homepage_locator = (By.CSS_SELECTOR, ".UserProfileEdit-homepage")
_edit_location_locator = (By.CSS_SELECTOR, ".UserProfileEdit-location")
_edit_occupation_locator = (By.CSS_SELECTOR, ".UserProfileEdit-occupation")
_profile_picture_placeholder_locator = (By.CSS_SELECTOR, ".Icon-anonymous-user")
_upload_picture_button_locator = (
By.CSS_SELECTOR,
".UserProfileEditPicture-file-input",
)
_uploaded_profile_picture_locator = (By.CSS_SELECTOR, ".UserAvatar-image")
_delete_picture_button_locator = (
By.CSS_SELECTOR,
".UserProfileEditPicture-delete-button button",
)
_cancel_delete_picture_locator = (
By.CSS_SELECTOR,
".ConfirmationDialog-cancel-button",
)
_confirm_delete_picture_locator = (
By.CSS_SELECTOR,
".ConfirmationDialog-confirm-button",
)
_picture_delete_success_text_locator = (By.CSS_SELECTOR, ".Notice-success p")
_edit_biography_locator = (By.CSS_SELECTOR, ".UserProfileEdit-biography")
_notifications_info_text_locator = (
By.CSS_SELECTOR,
".UserProfileEdit-notifications-aside",
)
_notification_checkbox_locator = (
By.CSS_SELECTOR,
".UserProfileEditNotification-input",
)
_notification_text_locator = (
By.CSS_SELECTOR,
".UserProfileEditNotification label",
)
_notifications_help_text_locator = (
By.CSS_SELECTOR,
".UserProfileEdit-notifications--help",
)
_edit_profile_submit_disabled_button_locator = (
By.CSS_SELECTOR,
".UserProfileEdit-submit-button.Button--disabled",
)
_edit_profile_submit_button_locator = (
By.CSS_SELECTOR,
".UserProfileEdit-submit-button",
)
_delete_profile_button_locator = (
By.CSS_SELECTOR,
".UserProfileEdit-delete-button",
)
_delete_profile_overlay_locator = (
By.CSS_SELECTOR,
".UserProfileEdit-deletion-modal",
)
_cancel_delete_profile_button_locator = (
By.CSS_SELECTOR,
".UserProfileEdit-deletion-modal .UserProfileEdit-cancel-button",
)
_confirm_delete_profile_button_locator = (
By.CSS_SELECTOR,
".UserProfileEdit-deletion-modal .UserProfileEdit-confirm-button",
)
_invalid_url_error_text_locator = (
By.CSS_SELECTOR,
".Notice-error .Notice-text",
)
def click_view_profile_link(self):
link = WebDriverWait(
self.driver, 20, ignored_exceptions=StaleElementReferenceException
).until(EC.element_to_be_clickable(self._view_profile_link_locator))
link.click()
self.wait.until(
EC.visibility_of_element_located((By.CSS_SELECTOR, ".UserProfile-name"))
)
@property
def email_field(self):
self.wait.until(EC.visibility_of_element_located(self._user_email_locator))
return self.find_element(*self._user_email_locator).get_attribute("value")
@property
def email_field_help_text(self):
self.wait.until(
EC.visibility_of_element_located(self._user_email_help_text_locator)
)
return self.find_element(*self._user_email_help_text_locator).text
def email_field_help_link(self):
self.wait.until(
EC.element_to_be_clickable(self._user_email_help_link_locator)
)
self.find_element(*self._user_email_help_link_locator).click()
# waits for the fxa support page to be opened
self.wait.until(
EC.visibility_of_element_located(
(By.CSS_SELECTOR, ".sumo-page-heading")
)
)
def link_to_fxa_account(self):
self.wait.until(EC.element_to_be_clickable(self._fxa_account_link_locator))
self.find_element(*self._fxa_account_link_locator).click()
# waits for the fxa account page to be opened - check logo visibility
self.wait.until(
EC.visibility_of_element_located((By.CSS_SELECTOR, ".flex h1 span"))
)
def display_name(self, value):
self.wait.until(
EC.visibility_of_element_located(self._edit_display_name_locator)
)
self.find_element(*self._edit_display_name_locator).send_keys(value)
@property
def display_name_field(self):
self.wait.until(
EC.visibility_of_element_located(self._edit_display_name_locator)
)
return self.find_element(*self._edit_display_name_locator)
def homepage_link(self, value):
self.wait.until(
EC.visibility_of_element_located(self._edit_homepage_locator)
)
self.find_element(*self._edit_homepage_locator).send_keys(value)
@property
def homepage_link_field(self):
self.wait.until(
EC.visibility_of_element_located(self._edit_homepage_locator)
)
return self.find_element(*self._edit_homepage_locator)
def location(self, value):
self.wait.until(
EC.visibility_of_element_located(self._edit_location_locator)
)
self.find_element(*self._edit_location_locator).send_keys(value)
@property
def location_field(self):
self.wait.until(
EC.visibility_of_element_located(self._edit_location_locator)
)
return self.find_element(*self._edit_location_locator)
def occupation(self, value):
self.wait.until(
EC.visibility_of_element_located(self._edit_occupation_locator)
)
self.find_element(*self._edit_occupation_locator).send_keys(value)
@property
def profile_avatar_placeholder(self):
self.wait.until(
EC.visibility_of_element_located(
self._profile_picture_placeholder_locator
)
)
return self.find_element(*self._profile_picture_placeholder_locator)
def upload_picture(self, image):
self.wait.until(
EC.visibility_of_element_located(self._upload_picture_button_locator)
)
button = self.find_element(*self._upload_picture_button_locator)
path = Path(os.getcwd())
img = str(path / "img" / image)
button.send_keys(img)
def profile_picture_is_displayed(self):
self.wait.until(
lambda _: self.is_element_displayed(
*self._uploaded_profile_picture_locator
)
)
return self
@property
def picture_source(self):
self.wait.until(
EC.visibility_of_element_located(self._uploaded_profile_picture_locator)
)
return self.find_element(
*self._uploaded_profile_picture_locator
).get_attribute("src")
def delete_profile_picture(self):
self.find_element(*self._delete_picture_button_locator).click()
self.wait.until(
EC.element_to_be_clickable(self._confirm_delete_picture_locator)
)
def cancel_delete_picture(self):
self.wait.until(
EC.element_to_be_clickable(self._cancel_delete_picture_locator)
)
self.find_element(*self._cancel_delete_picture_locator).click()
self.wait.until(
EC.element_to_be_clickable(self._delete_picture_button_locator)
)
def confirm_delete_picture(self):
self.wait.until(
EC.element_to_be_clickable(self._confirm_delete_picture_locator)
)
self.find_element(*self._confirm_delete_picture_locator).click()
self.wait.until(
EC.visibility_of_element_located(
self._picture_delete_success_text_locator
)
)
@property
def picture_delete_success_message(self):
self.wait.until(
EC.visibility_of_element_located(
self._picture_delete_success_text_locator
)
)
return self.find_element(*self._picture_delete_success_text_locator).text
def biography(self, value):
self.wait.until(
EC.visibility_of_element_located(self._edit_biography_locator)
)
self.find_element(*self._edit_biography_locator).send_keys(value)
@property
def notifications_info_text(self):
self.wait.until(
EC.visibility_of_element_located(self._notifications_info_text_locator)
)
return self.find_element(*self._notifications_info_text_locator).text
@property
def notifications_checkbox(self):
"""function used for developer notifications"""
self.wait.until(
lambda _: len(self.notification_text) == 8,
message=f"There were {len(self.notification_text)} notifications displayed, expected 8",
)
return self.find_elements(*self._notification_checkbox_locator)
@property
def notification_text(self):
self.wait.until(
EC.visibility_of_element_located(self._notification_text_locator)
)
items = self.find_elements(*self._notification_text_locator)
# the notifications endpoint takes a bit longer to respond, so a wait is helpful here
self.wait.until(
lambda _: len(items) > 0,
message=f"Expected notifications list to be loaded but the list contains {len(items)} items",
)
return items
@property
def notifications_help_text(self):
self.wait.until(
EC.visibility_of_element_located(self._notifications_help_text_locator)
)
return self.find_element(*self._notifications_help_text_locator).text
@property
def submit_changes_button_disabled(self):
return self.find_element(*self._edit_profile_submit_disabled_button_locator)
def update_profile(self):
"""Updates a user profile and expects to remain on the Edit Profile page (likely due to an error)"""
self.wait.until(
EC.element_to_be_clickable(self._edit_profile_submit_button_locator)
)
self.find_element(*self._edit_profile_submit_button_locator).click()
def submit_changes(self):
"""Updates a user profile and expects to navigate to the View Profile page"""
self.wait.until(
EC.element_to_be_clickable(self._edit_profile_submit_button_locator)
)
self.find_element(*self._edit_profile_submit_button_locator).click()
self.wait.until(
EC.visibility_of_element_located((By.CLASS_NAME, "UserProfile-name"))
)
def delete_account(self):
self.wait.until(
EC.element_to_be_clickable(self._delete_profile_button_locator)
)
self.find_element(*self._delete_profile_button_locator).click()
self.wait.until(
EC.visibility_of_element_located(self._delete_profile_overlay_locator)
)
def cancel_delete_account(self):
self.wait.until(
EC.element_to_be_clickable(self._cancel_delete_profile_button_locator)
)
self.find_element(*self._cancel_delete_profile_button_locator).click()
self.wait.until(
EC.invisibility_of_element_located(
self._cancel_delete_profile_button_locator
)
)
def confirm_delete_account(self):
self.wait.until(
EC.element_to_be_clickable(self._confirm_delete_profile_button_locator)
)
self.find_element(*self._confirm_delete_profile_button_locator).click()
return Home(self.driver, self.page.base_url).wait_for_page_to_load()
@property
def invalid_url_error_text(self):
self.wait.until(
EC.visibility_of_element_located(self._invalid_url_error_text_locator)
)
return self.find_element(*self._invalid_url_error_text_locator).text