pages/desktop/developers/manage_versions.py (277 lines of code) (raw):
import time
import pytest
from pypom import Region, Page
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
# from pages.desktop.developers.submit_addon import SubmitAddon
class ManageVersions(Page):
_addon_name_title_locator = (By.CSS_SELECTOR, 'div[class="section"] header h2')
_listing_visibility_section_locator = (
By.CSS_SELECTOR,
"#edit-addon h3:nth-child(1)",
)
_visible_listing_radio_locator = (By.CSS_SELECTOR, 'input[value="listed"]')
_visible_explainer_text_locator = (
By.CSS_SELECTOR,
"#addon-current-state label:nth-child(1)",
)
_invisible_listing_radio_locator = (By.CSS_SELECTOR, 'input[value="hidden"]')
_invisible_explainer_text_locator = (
By.CSS_SELECTOR,
"#addon-current-state label:nth-of-type(2)",
)
_hide_addon_confirmation_text_locator = (
By.CSS_SELECTOR,
"#modal-disable p:nth-child(1)",
)
_hide_addon_button_locator = (By.CSS_SELECTOR, "#modal-disable p button")
_hide_addon_cancel_link_locator = (By.CSS_SELECTOR, "#modal-disable p a")
_disabled_by_mozilla_locator = (By.CSS_SELECTOR, ".file-status > div")
_incomplete_status_locator = (By.CSS_SELECTOR, ".status-incomplete b")
_invisible_status_locator = (By.CSS_SELECTOR, ".status-disabled b")
_addon_listed_status_locator = (By.CSS_SELECTOR, ".addon-listed-status b")
_delete_addon_button_locator = (By.CLASS_NAME, "delete-button.delete-addon")
_upload_new_version_locator = (By.CSS_SELECTOR, ".button.version-upload")
# Version List Section
_version_list_locator = (By.ID, "version-list")
_current_version_status_locator = (
By.CSS_SELECTOR,
"#current-version-status .file-status > div:nth-child(1)",
)
_version_approval_status_locator = (
By.CSS_SELECTOR,
"#version-list .file-status div:nth-child(1)",
)
_disable_delete_version_button_locator = (By.CSS_SELECTOR, ".version-delete a")
_delete_version_help_text_locator = (By.CSS_SELECTOR, ".current-version-warning")
_delete_version_warning_locator = (By.CSS_SELECTOR, ".highlight.warning")
_delete_version_button_locator = (By.CSS_SELECTOR, ".modal-actions .delete-button")
_disable_version_button_locator = (
By.CSS_SELECTOR,
".modal-actions .disable-button",
)
_cancel_disable_version_link_locator = (By.CSS_SELECTOR, ".modal-actions .close")
_enable_version_button_locator = (By.CSS_SELECTOR, ".file-status button")
_cancel_request_review_button_locator = (By.ID, "cancel-review")
_request_review_button_locator = (By.CSS_SELECTOR, ".version-status-actions > form")
@staticmethod
def open_manage_versions_page_for_addon(selenium, base_url, addon):
return selenium.get(f"{base_url}/developers/addon/{addon}/versions")
def wait_for_page_to_load(self):
self.wait.until(EC.visibility_of_element_located(self._version_list_locator))
return self
@property
def version_page_title(self):
self.wait.until(
EC.visibility_of_element_located(self._addon_name_title_locator)
)
return self.find_element(*self._addon_name_title_locator).text
@property
def listing_visibility_section(self):
self.wait.until(
EC.visibility_of_element_located(self._listing_visibility_section_locator)
)
return self.find_element(*self._listing_visibility_section_locator).text
@property
def cancel_request_review_button(self):
self.wait.until(
EC.visibility_of_element_located(self._cancel_request_review_button_locator)
)
return self.find_element(*self._cancel_request_review_button_locator)
@property
def request_review_button(self):
self.wait.until(
EC.visibility_of_element_located(self._request_review_button_locator)
)
return self.find_element(*self._request_review_button_locator)
def click_request_review_button(self):
self.wait.until(
EC.visibility_of_element_located(self._request_review_button_locator)
)
return self.find_element(*self._request_review_button_locator).click()
def click_visible_radio_button(self):
self.wait.until(
EC.visibility_of_element_located(self._visible_listing_radio_locator)
)
return self.find_element(*self._visible_listing_radio_locator).click()
def click_upload_new_version_button(self):
self.wait.until(
EC.visibility_of_element_located(self._upload_new_version_locator)
)
return self.find_element(*self._upload_new_version_locator).click()
def set_addon_visible(self):
"""Selects the Visible option and checks that the radio button is selected"""
el = self.find_element(*self._visible_listing_radio_locator)
el.click()
assert el.is_selected()
@property
def incomplete_status_text(self):
self.wait.until(
EC.visibility_of_element_located(self._incomplete_status_locator)
)
return self.find_element(*self._incomplete_status_locator)
@property
def disabled_by_mozilla_text(self):
self.wait.until(
EC.visibility_of_element_located(self._disabled_by_mozilla_locator)
)
return self.find_element(*self._disabled_by_mozilla_locator)
@property
def visible_status_explainer(self):
self.wait.until(
EC.visibility_of_element_located(self._visible_explainer_text_locator)
)
return self.find_element(*self._visible_explainer_text_locator).text
@property
def invisible_status_explainer(self):
self.wait.until(
EC.visibility_of_element_located(self._invisible_explainer_text_locator)
)
return self.find_element(*self._invisible_explainer_text_locator).text
def set_addon_invisible(self):
"""Selects the Invisible option and checks that the radio button is selected"""
el = self.find_element(*self._invisible_listing_radio_locator)
el.click()
self.wait.until(
EC.element_to_be_clickable(
(By.CSS_SELECTOR, "#modal-disable p:nth-child(1)")
)
)
def click_hide_addon(self):
self.find_element(*self._hide_addon_button_locator).click()
@property
def hide_addon_confirmation_text(self):
self.wait.until(
EC.visibility_of_element_located(self._hide_addon_confirmation_text_locator)
)
return self.find_element(*self._hide_addon_confirmation_text_locator).text
def cancel_hide_addon_process(self):
"""Cancel the hide addon process and check that the Visible radio button is still selected"""
self.find_element(*self._hide_addon_cancel_link_locator).click()
assert self.find_element(*self._visible_listing_radio_locator).is_selected()
@property
def addon_listed_status(self):
self.wait.until(
EC.visibility_of_element_located(self._addon_listed_status_locator)
)
return self.find_element(*self._addon_listed_status_locator).text
@property
def incomplete_status(self):
self.wait.until(
EC.visibility_of_element_located(self._incomplete_status_locator)
)
return self.find_element(*self._incomplete_status_locator)
@property
def current_version_status(self):
self.wait.until(
EC.visibility_of_element_located(self._current_version_status_locator)
)
return self.find_element(*self._current_version_status_locator).text
@property
def version_approval_status(self):
self.wait.until(
EC.visibility_of_element_located(self._version_approval_status_locator)
)
return self.find_elements(*self._version_approval_status_locator)
def click_delete_disable_version(self):
self.find_element(*self._disable_delete_version_button_locator).click()
self.wait.until(
EC.element_to_be_clickable(
(By.CSS_SELECTOR, ".modal-actions .delete-button")
),
message="The Delete/Disable modal was not opened",
)
@property
def delete_disable_version_helptext(self):
self.wait.until(
EC.visibility_of_element_located(self._delete_version_help_text_locator)
)
return self.find_element(*self._delete_version_help_text_locator).text
@property
def delete_disable_version_warning(self):
self.wait.until(
EC.visibility_of_element_located(self._delete_version_warning_locator)
)
return self.find_element(*self._delete_version_warning_locator).text
def click_delete_version_button(self):
self.wait.until(EC.element_to_be_clickable(self._delete_version_button_locator))
self.find_element(*self._delete_version_button_locator).click()
def click_disable_version_button(self):
self.wait.until(
EC.element_to_be_clickable(self._disable_version_button_locator)
)
self.find_element(*self._disable_version_button_locator).click()
def click_cancel_version_delete_link(self):
self.wait.until(
EC.element_to_be_clickable(self._cancel_disable_version_link_locator)
)
return self.find_element(*self._cancel_disable_version_link_locator).click()
def click_enable_version(self):
"""Allows developers to re-enable a version that was previously disabled"""
self.wait.until(EC.element_to_be_clickable(self._enable_version_button_locator))
self.find_element(*self._enable_version_button_locator).click()
def wait_for_version_autoapproval(self, value):
"""Method that verifies if auto-approval occurs within a set time"""
timeout_start = time.time()
# auto-approvals should normally take ~5 minutes;
# set a loop to verify if approval occurs within this interval
while time.time() < timeout_start + 420:
# refresh the page to check if the status has changed
self.driver.refresh()
if value not in self.version_approval_status[0].text:
# wait 30 seconds before we refresh again
time.sleep(30)
# break the loop if the status changed to the expected value within set time
else:
break
# if auto-approval took longer than normal, we want to fail the test and capture the final status
else:
pytest.fail(
f"Autoapproval took longer than normal; "
f'Addon final status was "{self.version_approval_status[0].text}" instead of "{value}"'
)
def delete_addon(self):
self.find_element(*self._delete_addon_button_locator).click()
return self.DeleteAddonModal(self).wait_for_region_to_load()
def click_cancel_review_request(self):
self.find_element(*self._cancel_request_review_button_locator).click()
return self.CancelReviewRequestModal(self).wait_for_region_to_load()
def invisible_status_text(self):
self.wait.until(
EC.visibility_of_element_located(
self._invisible_status_locator
)
)
return self.find_element(*self._invisible_status_locator).text
class CancelReviewRequestModal(Region):
_root_locator = (By.ID, 'modal-cancel')
_are_you_sure_message_locator = (By.CSS_SELECTOR, '#modal-cancel > form:nth-child(1) > p:nth-child(3)')
_cancel_your_review_request_message_locator = (By.CSS_SELECTOR, '#modal-cancel > form:nth-child(1) > p:nth-child(2)')
_cancel_review_request_button_locator = (By.CSS_SELECTOR, '#modal-cancel > form:nth-child(1) > p:nth-child(6) > button:nth-child(1)')
def wait_for_region_to_load(self):
self.wait.until(EC.visibility_of_element_located(self._root_locator))
return self
@property
def are_you_sure_message(self):
return self.find_element(*self._are_you_sure_message_locator)
@property
def cancel_your_review_request_message_locator(self):
return self.find_element(*self._cancel_your_review_request_message_locator)
def click_cancel_review_request_button(self):
self.wait.until(EC.visibility_of_element_located(self._cancel_review_request_button_locator))
self.find_element(*self._cancel_review_request_button_locator).click()
return self
class DeleteAddonModal(Region):
_root_locator = (By.ID, "modal-delete")
_delete_confirmation_string_locator = (
By.CSS_SELECTOR,
"p:nth-of-type(2) > label",
)
_delete_confirmation_text_input_locator = (
By.CSS_SELECTOR,
'input[name="slug"]',
)
_delete_button_locator = (By.CSS_SELECTOR, ".delete-button")
def wait_for_region_to_load(self):
self.wait.until(EC.visibility_of_element_located(self._root_locator))
return self
@property
def delete_confirmation_string(self):
"""This is the addon slug which is required to confirm deleting an addon"""
return self.find_element(
*self._delete_confirmation_string_locator
).text.split()[-1]
def input_delete_confirmation_string(self):
self.find_element(*self._delete_confirmation_text_input_locator).send_keys(
self.delete_confirmation_string
)
def confirm_delete_addon(self):
self.find_element(*self._delete_button_locator).click()
from pages.desktop.developers.addons_manage import ManageAddons
return ManageAddons(self.driver, self.page.base_url).wait_for_page_to_load()