зеркало из https://github.com/mozilla/kitsune.git
- Expanding Playwright AAQ coverage to test all "Question Tools" functionalities from posted questions. (#5823)
- Refactored some bits and pieces. - Updated the workflow file to schedule the newly added coverage for execution. - Updated workflow to execute Firefox tests on Monday, Wednesday and Friday and Chrome tests on Tuesday and Thursday.
This commit is contained in:
Родитель
b77eb6c540
Коммит
4c4fd57879
|
@ -1,12 +1,9 @@
|
|||
name: Playwright Tests
|
||||
on:
|
||||
schedule:
|
||||
- cron: '0 5 * * 1,3,5'
|
||||
# Firefox tests running on Monday, Wednesday and Friday. Chrome runs Tuesday and Thursday.
|
||||
- cron: '0 5 * * 1,2,3,4,5'
|
||||
|
||||
jobs:
|
||||
playwright:
|
||||
name: 'Playwright Tests'
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
TEST_ACCOUNT_12: ${{secrets.AUTOMATION_TEST_ACCOUNT_12}}
|
||||
TEST_ACCOUNT_13: ${{secrets.AUTOMATION_TEST_ACCOUNT_13}}
|
||||
|
@ -19,7 +16,12 @@ jobs:
|
|||
TEST_ACCOUNT_SPECIAL_CHARS: ${{secrets.AUTOMATION_TEST_ACCOUNT_SPECIAL_CHARS}}
|
||||
TEST_ACCOUNTS_PS: ${{secrets.AUTOMATION_ACCOUNTS_PASSWORD}}
|
||||
TEST_ACCOUNT_MODERATOR: ${{secrets.AUTOMATION_MODERATOR_ACCOUNT}}
|
||||
BROWSER: ${{secrets.BROWSER}}
|
||||
|
||||
|
||||
jobs:
|
||||
playwright_tests:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Set up Python
|
||||
|
@ -36,156 +38,100 @@ jobs:
|
|||
run: |
|
||||
pip3 install playwright
|
||||
python -m playwright install
|
||||
- name: Creating User Sessions
|
||||
- name: Set up browsers env
|
||||
if: "github.event_name == 'schedule' || github.event_name == 'workflow_run'"
|
||||
run: |
|
||||
current_day=$(date +\%u)
|
||||
if [ $current_day -eq 1 ] || [ $current_day -eq 3 ] || [ $current_day -eq 5 ]; then
|
||||
echo "BROWSER=firefox" >> $GITHUB_ENV
|
||||
elif [ $current_day -eq 2 ] || [ $current_day -eq 4 ]; then
|
||||
echo "BROWSER=chrome" >> $GITHUB_ENV
|
||||
fi
|
||||
- name: Creating User Sessions for ${{ env.BROWSER }}
|
||||
id: create-sessions
|
||||
working-directory: playwright_tests
|
||||
run: |
|
||||
poetry run pytest -m loginSessions --browser firefox --reruns 1 --html=reports/creating_user_sessions.html --capture=tee-sys
|
||||
- name: Run Homepage tests (Firefox)
|
||||
poetry run pytest -m loginSessions --browser ${{ env.BROWSER }} --reruns 1 --html=reports/creating_user_sessions.html --capture=tee-sys
|
||||
- name: Run Homepage tests (${{ env.BROWSER }})
|
||||
working-directory: playwright_tests
|
||||
if: success() || failure() && steps.create-sessions.outcome == 'success'
|
||||
run: |
|
||||
poetry run pytest -m homePageTests --numprocesses 2 --browser firefox --reruns 1 --html=reports/firefox_homepage_tests_report.html --capture=tee-sys
|
||||
- name: Run Homepage tests (Chrome)
|
||||
poetry run pytest -m homePageTests --numprocesses 2 --browser ${{ env.BROWSER }} --reruns 1 --html=reports/${{ env.BROWSER }}_homepage_tests_report.html --capture=tee-sys
|
||||
- name: Run Top-Navbar tests (${{ env.BROWSER }})
|
||||
working-directory: playwright_tests
|
||||
if: success() || failure() && steps.create-sessions.outcome == 'success'
|
||||
run: |
|
||||
poetry run pytest -m homePageTests --numprocesses 2 --browser chrome --reruns 1 --html=reports/chrome_homepage_tests_report.html --capture=tee-sys
|
||||
- name: Run Top-Navbar tests (Firefox)
|
||||
poetry run pytest -m topNavbarTests --numprocesses 2 --browser ${{ env.BROWSER }} --reruns 1 --html=reports/${{ env.BROWSER }}_top_navbar_tests_report.html --capture=tee-sys
|
||||
- name: Run Footer tests (${{ env.BROWSER }})
|
||||
working-directory: playwright_tests
|
||||
if: success() || failure() && steps.create-sessions.outcome == 'success'
|
||||
run: |
|
||||
poetry run pytest -m topNavbarTests --numprocesses 2 --browser firefox --reruns 1 --html=reports/firefox_top_navbar_tests_report.html --capture=tee-sys
|
||||
- name: Run Top-Navbar tests (Chrome)
|
||||
poetry run pytest -m footerSectionTests --numprocesses 2 --browser ${{ env.BROWSER }} --reruns 1 --html=reports/${{ env.BROWSER }}_footer_tests_report.html --capture=tee-sys
|
||||
- name: Run Contribute Pages tests (${{ env.BROWSER }})
|
||||
working-directory: playwright_tests
|
||||
if: success() || failure() && steps.create-sessions.outcome == 'success'
|
||||
run: |
|
||||
poetry run pytest -m topNavbarTests --numprocesses 2 --browser chrome --reruns 1 --html=reports/chrome_top_navbar_tests_report.html --capture=tee-sys
|
||||
- name: Run Footer tests (Firefox)
|
||||
poetry run pytest -m contributePagesTests --numprocesses 2 --browser ${{ env.BROWSER }} --reruns 1 --html=reports/${{ env.BROWSER }}_contribute_page_tests_report.html --capture=tee-sys
|
||||
- name: Run Messaging System Tests (${{ env.BROWSER }})
|
||||
working-directory: playwright_tests
|
||||
if: success() || failure() && steps.create-sessions.outcome == 'success'
|
||||
run: |
|
||||
poetry run pytest -m footerSectionTests --numprocesses 2 --browser firefox --reruns 1 --html=reports/firefox_footer_tests_report.html --capture=tee-sys
|
||||
- name: Run Footer tests (Chrome)
|
||||
poetry run pytest -m messagingSystem --numprocesses 2 --browser ${{ env.BROWSER }} --reruns 1 --html=reports/${{ env.BROWSER }}_messaging_system_tests_report.html --capture=tee-sys
|
||||
- name: Run User Contribution Page Tests (${{ env.BROWSER }})
|
||||
working-directory: playwright_tests
|
||||
if: success() || failure() && steps.create-sessions.outcome == 'success'
|
||||
run: |
|
||||
poetry run pytest -m footerSectionTests --numprocesses 2 --browser chrome --reruns 1 --html=reports/chrome_footer_tests_report.html --capture=tee-sys
|
||||
- name: Run Contribute Pages tests (Firefox)
|
||||
poetry run pytest -m userContributionTests --numprocesses 2 --browser ${{ env.BROWSER }} --reruns 1 --html=reports/${{ env.BROWSER }}_user_contribution_tests.html --capture=tee-sys
|
||||
- name: Run User Page Tests (${{ env.BROWSER }})
|
||||
working-directory: playwright_tests
|
||||
if: success() || failure() && steps.create-sessions.outcome == 'success'
|
||||
run: |
|
||||
poetry run pytest -m contributePagesTests --numprocesses 2 --browser firefox --reruns 1 --html=reports/firefox_contribute_page_tests_report.html --capture=tee-sys
|
||||
- name: Run Contribute Page tests (Chrome)
|
||||
poetry run pytest -m userProfile --numprocesses 2 --browser ${{ env.BROWSER }} --reruns 1 --html=reports/${{ env.BROWSER }}_user_page_tests.html --capture=tee-sys
|
||||
- name: Run User Settings Tests (${{ env.BROWSER }})
|
||||
working-directory: playwright_tests
|
||||
if: success() || failure() && steps.create-sessions.outcome == 'success'
|
||||
run: |
|
||||
poetry run pytest -m contributePagesTests --numprocesses 2 --browser chrome --reruns 1 --html=reports/chrome_contribute_page_tests_report.html --capture=tee-sys
|
||||
- name: Run Messaging System Tests (Firefox)
|
||||
poetry run pytest -m userSettings --numprocesses 2 --browser ${{ env.BROWSER }} --reruns 1 --html=reports/${{ env.BROWSER }}_user_settings_page_tests.html --capture=tee-sys
|
||||
- name: Run User Profile Tests (${{ env.BROWSER }})
|
||||
working-directory: playwright_tests
|
||||
if: success() || failure() && steps.create-sessions.outcome == 'success'
|
||||
run: |
|
||||
poetry run pytest -m messagingSystem --numprocesses 2 --browser firefox --reruns 1 --html=reports/firefox_messaging_system_tests_report.html --capture=tee-sys
|
||||
- name: Run Messaging System Tests (Chrome)
|
||||
poetry run pytest -m editUserProfileTests --browser ${{ env.BROWSER }} --reruns 1 --html=reports/${{ env.BROWSER }}_user_profile_page_tests.html --capture=tee-sys
|
||||
- name: Run User Questions Tests (${{ env.BROWSER }})
|
||||
working-directory: playwright_tests
|
||||
if: success() || failure() && steps.create-sessions.outcome == 'success'
|
||||
run: |
|
||||
poetry run pytest -m messagingSystem --numprocesses 2 --browser chrome --reruns 1 --html=reports/chrome_messaging_system_tests_report.html --capture=tee-sys
|
||||
- name: Run User Contribution Page Tests (Firefox)
|
||||
poetry run pytest -m userQuestions --numprocesses 2 --browser ${{ env.BROWSER }} --reruns 1 --html=reports/${{ env.BROWSER }}_user_questions_page_tests.html --capture=tee-sys
|
||||
- name: Run Contact Support Page Tests (${{ env.BROWSER }})
|
||||
working-directory: playwright_tests
|
||||
if: success() || failure() && steps.create-sessions.outcome == 'success'
|
||||
run: |
|
||||
poetry run pytest -m userContributionTests --numprocesses 2 --browser firefox --reruns 1 --html=reports/firefox_user_contribution_tests.html --capture=tee-sys
|
||||
- name: Run User Contribution Page Tests (Chrome)
|
||||
poetry run pytest -m contactSupportPage --numprocesses 2 --browser ${{ env.BROWSER }} --reruns 1 --html=reports/${{ env.BROWSER }}_contact_support_page_tests.html --capture=tee-sys
|
||||
- name: Run Product Solutions Page Tests (${{ env.BROWSER }})
|
||||
working-directory: playwright_tests
|
||||
if: success() || failure() && steps.create-sessions.outcome == 'success'
|
||||
run: |
|
||||
poetry run pytest -m userContributionTests --numprocesses 2 --browser chrome --reruns 1 --html=reports/chrome_user_contribution_tests.html --capture=tee-sys
|
||||
- name: Run User Page Tests (Firefox)
|
||||
poetry run pytest -m productSolutionsPage --numprocesses 2 --browser ${{ env.BROWSER }} --reruns 1 --html=reports/${{ env.BROWSER }}_product_solutions_page_tests.html --capture=tee-sys
|
||||
- name: Run Product Topics Page Tests (${{ env.BROWSER }})
|
||||
working-directory: playwright_tests
|
||||
if: success() || failure() && steps.create-sessions.outcome == 'success'
|
||||
run: |
|
||||
poetry run pytest -m userProfile --numprocesses 2 --browser firefox --reruns 1 --html=reports/firefox_user_page_tests.html --capture=tee-sys
|
||||
- name: Run User Page Tests (Chrome)
|
||||
poetry run pytest -m productTopicsPage --numprocesses 2 --browser ${{ env.BROWSER }} --reruns 1 --html=reports/${{ env.BROWSER }}_product_topics_page_tests.html --capture=tee-sys
|
||||
- name: Run AAQ Tests (${{ env.BROWSER }})
|
||||
working-directory: playwright_tests
|
||||
if: success() || failure() && steps.create-sessions.outcome == 'success'
|
||||
run: |
|
||||
poetry run pytest -m userProfile --numprocesses 2 --browser chrome --reruns 1 --html=reports/chrome_user_page_tests.html --capture=tee-sys
|
||||
- name: Run User Settings Tests (Firefox)
|
||||
poetry run pytest -m aaqPage --numprocesses 2 --browser ${{ env.BROWSER }} --reruns 1 --html=reports/${{ env.BROWSER }}_aaq_tests.html --capture=tee-sys
|
||||
- name: Run AAQ Questions Tests (${{ env.BROWSER }})
|
||||
working-directory: playwright_tests
|
||||
if: success() || failure() && steps.create-sessions.outcome == 'success'
|
||||
run: |
|
||||
poetry run pytest -m userSettings --numprocesses 2 --browser firefox --reruns 1 --html=reports/firefox_user_settings_page_tests.html --capture=tee-sys
|
||||
- name: Run User Settings Tests (Chrome)
|
||||
working-directory: playwright_tests
|
||||
if: success() || failure() && steps.create-sessions.outcome == 'success'
|
||||
run: |
|
||||
poetry run pytest -m userSettings --numprocesses 2 --browser chrome --reruns 1 --html=reports/chrome_user_settings_page_tests.html --capture=tee-sys
|
||||
- name: Run User Profile Tests (Firefox)
|
||||
working-directory: playwright_tests
|
||||
if: success() || failure() && steps.create-sessions.outcome == 'success'
|
||||
run: |
|
||||
poetry run pytest -m editUserProfileTests --browser firefox --reruns 1 --html=reports/firefox_user_profile_page_tests.html --capture=tee-sys
|
||||
- name: Run Edit User Profile Tests (Chrome)
|
||||
working-directory: playwright_tests
|
||||
if: success() || failure() && steps.create-sessions.outcome == 'success'
|
||||
run: |
|
||||
poetry run pytest -m editUserProfileTests --browser chrome --reruns 1 --html=reports/chrome_user_profile_page_tests.html --capture=tee-sys
|
||||
- name: Run User Questions Tests (Firefox)
|
||||
working-directory: playwright_tests
|
||||
if: success() || failure() && steps.create-sessions.outcome == 'success'
|
||||
run: |
|
||||
poetry run pytest -m userQuestions --numprocesses 2 --browser firefox --reruns 1 --html=reports/firefox_user_questions_page_tests.html --capture=tee-sys
|
||||
- name: Run User Questions Tests (Chrome)
|
||||
working-directory: playwright_tests
|
||||
if: success() || failure() && steps.create-sessions.outcome == 'success'
|
||||
run: |
|
||||
poetry run pytest -m userQuestions --numprocesses 2 --browser chrome --reruns 1 --html=reports/chrome_user_questions_page_tests.html --capture=tee-sys
|
||||
- name: Run Contact Support Page Tests (Firefox)
|
||||
working-directory: playwright_tests
|
||||
if: success() || failure() && steps.create-sessions.outcome == 'success'
|
||||
run: |
|
||||
poetry run pytest -m contactSupportPage --numprocesses 2 --browser firefox --reruns 1 --html=reports/firefox_contact_support_page_tests.html --capture=tee-sys
|
||||
- name: Run Contact Support Page Tests (Chrome)
|
||||
working-directory: playwright_tests
|
||||
if: success() || failure() && steps.create-sessions.outcome == 'success'
|
||||
run: |
|
||||
poetry run pytest -m contactSupportPage --numprocesses 2 --browser chrome --reruns 1 --html=reports/chrome_contact_support_page_tests.html --capture=tee-sys
|
||||
- name: Run Product Solutions Page Tests (Firefox)
|
||||
working-directory: playwright_tests
|
||||
if: success() || failure() && steps.create-sessions.outcome == 'success'
|
||||
run: |
|
||||
poetry run pytest -m productSolutionsPage --numprocesses 2 --browser firefox --reruns 1 --html=reports/firefox_product_solutions_page_tests.html --capture=tee-sys
|
||||
- name: Run Product Solutions Page Tests (Chrome)
|
||||
working-directory: playwright_tests
|
||||
if: success() || failure() && steps.create-sessions.outcome == 'success'
|
||||
run: |
|
||||
poetry run pytest -m productSolutionsPage --numprocesses 2 --browser chrome --reruns 1 --html=reports/chrome_product_solutions_page_tests.html --capture=tee-sys
|
||||
- name: Run Product Topics Page Tests (Firefox)
|
||||
working-directory: playwright_tests
|
||||
if: success() || failure() && steps.create-sessions.outcome == 'success'
|
||||
run: |
|
||||
poetry run pytest -m productTopicsPage --numprocesses 2 --browser firefox --reruns 1 --html=reports/firefox_product_topics_page_tests.html --capture=tee-sys
|
||||
- name: Run Product Topics Page Tests (Chrome)
|
||||
working-directory: playwright_tests
|
||||
if: success() || failure() && steps.create-sessions.outcome == 'success'
|
||||
run: |
|
||||
poetry run pytest -m productTopicsPage --numprocesses 2 --browser chrome --reruns 1 --html=reports/chrome_product_topics_page_tests.html --capture=tee-sys
|
||||
- name: Run AAQ Tests (Firefox)
|
||||
working-directory: playwright_tests
|
||||
if: success() || failure() && steps.create-sessions.outcome == 'success'
|
||||
run: |
|
||||
poetry run pytest -m aaqPage --numprocesses 2 --browser firefox --reruns 1 --html=reports/firefox_aaq_tests.html --capture=tee-sys
|
||||
- name: Run AAQ Tests (Chrome)
|
||||
working-directory: playwright_tests
|
||||
if: success() || failure() && steps.create-sessions.outcome == 'success'
|
||||
run: |
|
||||
poetry run pytest -m aaqPage --numprocesses 2 --browser chrome --reruns 1 --html=reports/chrome_aaq_tests.html --capture=tee-sys
|
||||
poetry run pytest -m postedQuestions --numprocesses 2 --browser ${{ env.BROWSER }} --reruns 1 --html=reports/${{ env.BROWSER }}_aaq_questions_tests.html --capture=tee-sys
|
||||
- name: Combine Reports
|
||||
working-directory: playwright_tests
|
||||
if: success() || failure()
|
||||
run: |
|
||||
cat reports/*.html > reports/combined_report.html
|
||||
cat reports/*.html > reports/combined_report_${{ env.BROWSER }}.html
|
||||
- name: Upload the combined test report as artifact
|
||||
if: success() || failure()
|
||||
uses: actions/upload-artifact@v2
|
||||
|
|
|
@ -6,83 +6,121 @@ class BasePage:
|
|||
def __init__(self, page: Page):
|
||||
self._page = page
|
||||
|
||||
# Single locator retrieval.
|
||||
# Waits for DOM load to finish.
|
||||
def _get_element_locator(self, xpath: str) -> Locator:
|
||||
self.__wait_for_dom_load_to_finnish()
|
||||
return self._page.locator(xpath)
|
||||
|
||||
# Multiple locators retrieval.
|
||||
# Waits for DOM load to finish.
|
||||
def _get_elements_locators(self, xpath: str) -> list[Locator]:
|
||||
self.__wait_for_dom_load_to_finnish()
|
||||
return self._page.locator(xpath).all()
|
||||
|
||||
# Single locator retrieval without wait.
|
||||
def _get_element_locator_no_wait(self, xpath: str) -> Locator:
|
||||
return self._page.locator(xpath)
|
||||
|
||||
# Element handle retrieval.
|
||||
def _get_element_handles(self, xpath: str) -> list[ElementHandle]:
|
||||
return self._get_element_locator(xpath).element_handles()
|
||||
|
||||
# Multiple element handles retrieval.
|
||||
def _get_element_handle(self, xpath: str) -> ElementHandle:
|
||||
return self._get_element_locator(xpath).element_handle()
|
||||
|
||||
# Multiples elements inner text retrieval.
|
||||
def _get_text_of_elements(self, xpath: str) -> list[str]:
|
||||
return self._get_element_locator(xpath).all_inner_texts()
|
||||
|
||||
# Element inner text retrieval.
|
||||
def _get_text_of_element(self, xpath: str) -> str:
|
||||
return self._get_element_locator(xpath).inner_text()
|
||||
|
||||
# Elements count retrieval.
|
||||
def _get_elements_count(self, xpath: str) -> int:
|
||||
return self._get_element_locator(xpath).count()
|
||||
|
||||
# Fetching a particular element attribute value.
|
||||
def _get_element_attribute_value(self, xpath: str, attribute: str) -> str:
|
||||
return self._get_element_locator(xpath).get_attribute(attribute)
|
||||
|
||||
def _get_element_inner_text_from_page(self, xpath: str) -> str:
|
||||
return self._page.inner_text(xpath)
|
||||
# Fetch a particular element locator attribute value.
|
||||
def _get_element_locator_attribute_value(self, locator: Locator, attribute: str) -> str:
|
||||
self.__wait_for_dom_load_to_finnish()
|
||||
return locator.get_attribute(attribute)
|
||||
|
||||
# Fetching a particular element input value.
|
||||
def _get_element_input_value(self, xpath: str) -> str:
|
||||
return self._get_element_locator(xpath).input_value()
|
||||
|
||||
# Get element inner text from page.
|
||||
def _get_element_inner_text_from_page(self, xpath: str) -> str:
|
||||
return self._page.inner_text(xpath)
|
||||
|
||||
# Clicking on a particular element.
|
||||
def _click(self, xpath: str):
|
||||
self._get_element_locator(xpath).click()
|
||||
|
||||
# Clicking on a particular element without wait.
|
||||
def _click_without_wait(self, xpath: str):
|
||||
self._get_element_locator_no_wait(xpath).click()
|
||||
|
||||
# Filling text to an element input.
|
||||
def _fill(self, xpath: str, text: str):
|
||||
self._get_element_locator(xpath).fill(text)
|
||||
|
||||
# Typing text inside an input field with a given delay.
|
||||
def _type(self, xpath: str, text: str, delay: int):
|
||||
self._get_element_locator(xpath).type(text=text, delay=delay)
|
||||
|
||||
# Type inside an input field by pressing a particular key.
|
||||
def _press_a_key(self, xpath: str, key: str):
|
||||
self._get_element_locator(xpath).press(key)
|
||||
|
||||
# Clearing an input field.
|
||||
def _clear_field(self, xpath: str):
|
||||
self._get_element_locator(xpath).clear()
|
||||
|
||||
# Clicking on a particular element by index.
|
||||
def _click_on_an_element_by_index(self, xpath: str, index: int):
|
||||
self._get_element_locator(xpath).nth(index).click()
|
||||
|
||||
# Clicking on the first element from a locator list.
|
||||
def _click_on_first_item(self, xpath: str):
|
||||
self._get_element_locator(xpath).first.click()
|
||||
|
||||
# Choosing an option by label from a select element.
|
||||
def _select_option_by_label(self, xpath: str, label_name: str):
|
||||
self._get_element_locator(xpath).select_option(label=label_name)
|
||||
|
||||
# Choosing an option by value from a select element.
|
||||
def _select_option_by_value(self, xpath: str, value: str):
|
||||
self._get_element_locator(xpath).select_option(value=value)
|
||||
|
||||
# Accept a dialog.
|
||||
def _accept_dialog(self):
|
||||
self._page.on("dialog", lambda dialog: dialog.accept())
|
||||
|
||||
# Hover over a particular element.
|
||||
def _hover_over_element(self, xpath: str):
|
||||
self._get_element_locator(xpath).hover()
|
||||
|
||||
# Verifying if a particular element is visible.
|
||||
def _is_element_visible(self, xpath: str) -> bool:
|
||||
return self._get_element_locator(xpath).is_visible()
|
||||
|
||||
# Verifying if a particular checkbox is checked.
|
||||
def _is_checkbox_checked(self, xpath: str) -> bool:
|
||||
return self._get_element_locator(xpath).is_checked()
|
||||
|
||||
# Custom wait for DOM load to finish.
|
||||
def __wait_for_dom_load_to_finnish(self):
|
||||
self._page.wait_for_load_state("domcontentloaded")
|
||||
self._page.wait_for_load_state("load")
|
||||
|
||||
# Custom wait for selector to be displayed.
|
||||
def _wait_for_selector(self, xpath: str):
|
||||
try:
|
||||
self._page.wait_for_selector(xpath, timeout=3500)
|
||||
|
|
|
@ -14,6 +14,8 @@ from requests.exceptions import HTTPError
|
|||
|
||||
@pytest.mark.usefixtures("setup")
|
||||
class TestUtilities:
|
||||
|
||||
# Fetching test data from json files.
|
||||
with open("test_data/profile_edit.json", "r") as edit_test_data_file:
|
||||
profile_edit_test_data = json.load(edit_test_data_file)
|
||||
edit_test_data_file.close()
|
||||
|
@ -38,6 +40,7 @@ class TestUtilities:
|
|||
general_test_data = json.load(general_test_data_file)
|
||||
general_test_data_file.close()
|
||||
|
||||
# Fetching user secrets from GH.
|
||||
user_secrets_accounts = {
|
||||
"TEST_ACCOUNT_12": os.environ.get("TEST_ACCOUNT_12"),
|
||||
"TEST_ACCOUNT_13": os.environ.get("TEST_ACCOUNT_13"),
|
||||
|
@ -56,7 +59,7 @@ class TestUtilities:
|
|||
def clear_fxa_email(self, fxa_username: str):
|
||||
requests.delete(f"https://restmail.net/mail/{fxa_username}")
|
||||
|
||||
# Mechanism of fetching the fxa verification code from restamil
|
||||
# Mechanism of fetching the fxa verification code from restamil.
|
||||
def get_fxa_verification_code(self, fxa_username: str, max_attempts=5, poll_interval=5) -> str:
|
||||
for attempt in range(max_attempts):
|
||||
try:
|
||||
|
@ -80,29 +83,26 @@ class TestUtilities:
|
|||
print(fxa_verification_code)
|
||||
time.sleep(poll_interval)
|
||||
|
||||
# Extracting username from e-mail mechanism
|
||||
# Extracting username from e-mail mechanism.
|
||||
def username_extraction_from_email(self, string_to_analyze: str) -> str:
|
||||
return re.match(r"(.+)@", string_to_analyze).group(1)
|
||||
|
||||
# Random number generator.
|
||||
def generate_random_number(self, min_value, max_value) -> int:
|
||||
return random.randint(min_value, max_value)
|
||||
|
||||
# Extracting numbers from string.
|
||||
def number_extraction_from_string(self, string_to_analyze: str) -> int:
|
||||
return int(re.findall(r"\d+", string_to_analyze)[0])
|
||||
|
||||
# Defining the logging mechanism
|
||||
# Defining the logging mechanism.
|
||||
def get_logger(self):
|
||||
logger_name = inspect.stack()[1][3]
|
||||
logger = logging.getLogger(logger_name)
|
||||
|
||||
file_handler = logging.FileHandler("reports/logs/logfile.log")
|
||||
|
||||
formatter = logging.Formatter("%(asctime)s : %(levelname)s : %(name)s : %(message)s")
|
||||
|
||||
file_handler.setFormatter(formatter)
|
||||
|
||||
logger.addHandler(file_handler)
|
||||
|
||||
logger.setLevel(logging.INFO)
|
||||
|
||||
return logger
|
||||
|
@ -123,9 +123,10 @@ class TestUtilities:
|
|||
def navigate_to_homepage(self):
|
||||
self.page.goto(HomepageMessages.STAGE_HOMEPAGE_URL)
|
||||
|
||||
# Navigating to a specific given link
|
||||
# Navigating to a specific given link and waiting for the load state to finish.
|
||||
def navigate_to_link(self, link: str):
|
||||
self.page.goto(link)
|
||||
self.page.wait_for_load_state("domcontentloaded")
|
||||
|
||||
# Wait for a given timeout
|
||||
def wait_for_given_timeout(self, milliseconds: int):
|
||||
|
@ -138,11 +139,13 @@ class TestUtilities:
|
|||
def store_session_cookies(self, session_file_name: str):
|
||||
self.context.storage_state(path=f"core/sessions/.auth/{session_file_name}.json")
|
||||
|
||||
# Deleting page cookies.
|
||||
def delete_cookies(self):
|
||||
self.context.clear_cookies()
|
||||
# Reloading the page for the deletion to take immediate action.
|
||||
self.page.reload()
|
||||
|
||||
# Starting an existing session by applying session cookies.
|
||||
def start_existing_session(self, session_file_name: str):
|
||||
with open(f"core/sessions/.auth/{session_file_name}.json", 'r') as file:
|
||||
cookies_data = json.load(file)
|
||||
|
@ -151,11 +154,14 @@ class TestUtilities:
|
|||
# session
|
||||
self.page.reload()
|
||||
|
||||
# Fetching the user agent.
|
||||
def get_user_agent(self) -> str:
|
||||
return self.page.evaluate('window.navigator.userAgent ')
|
||||
|
||||
# Replacing special chars from an account.
|
||||
def replace_special_chars_account(self, account: str) -> str:
|
||||
return account.replace(account, "testMozillaSpecialChars")
|
||||
|
||||
# Removing a particular character from a given string.
|
||||
def remove_character_from_string(self, string: str, character_to_remove: str) -> str:
|
||||
return string.replace(character_to_remove, "")
|
||||
|
|
|
@ -11,7 +11,8 @@ class AAQFlow(AAQFormPage, ProductSolutionsPage, TopNavbar, TestUtilities, Quest
|
|||
def __init__(self, page: Page):
|
||||
super().__init__(page)
|
||||
|
||||
# Mozilla VPN has an extra optional dropdown menu for choosing an operating system
|
||||
# Submitting an aaq question for a product flow.
|
||||
# Mozilla VPN has an extra optional dropdown menu for choosing an operating system.
|
||||
def submit_an_aaq_question_for_a_product(self,
|
||||
subject: str,
|
||||
topic_name: str,
|
||||
|
@ -32,9 +33,11 @@ class AAQFlow(AAQFormPage, ProductSolutionsPage, TopNavbar, TestUtilities, Quest
|
|||
current_page_url = self._page.url
|
||||
|
||||
# Returning the posted question subject and url for further usage.
|
||||
return {"aaq_subject": question_subject, "question_page_url": current_page_url}
|
||||
return {"aaq_subject": question_subject, "question_page_url": current_page_url,
|
||||
"question_body": body}
|
||||
|
||||
# Mozilla VPN has an extra optional dropdown menu for choosing an operating system
|
||||
# Populating the aaq form fields with given values without submitting the form.
|
||||
# Mozilla VPN has an extra optional dropdown menu for choosing an operating system.
|
||||
def add__valid_data_to_all_input_fields_without_submitting(self,
|
||||
subject: str,
|
||||
topic_value: str,
|
||||
|
@ -69,6 +72,7 @@ class AAQFlow(AAQFormPage, ProductSolutionsPage, TopNavbar, TestUtilities, Quest
|
|||
# Returning the entered question subject for further usage.
|
||||
return aaq_subject
|
||||
|
||||
# Adding an image to the aaq form.
|
||||
def adding_an_image_to_aaq_form(self):
|
||||
super().get_upload_image_button_locator().set_input_files(
|
||||
super().aaq_question_test_data["valid_firefox_question"]["image_path"]
|
||||
|
|
|
@ -10,6 +10,7 @@ class AddKbArticleFlow(TestUtilities, SubmitKBArticlePage):
|
|||
def __init__(self, page: Page):
|
||||
super().__init__(page)
|
||||
|
||||
# Submitting a KB article flow.
|
||||
def submit_simple_kb_article(self) -> str:
|
||||
self._page.goto(KBArticlePageMessages.CREATE_NEW_KB_ARTICLE_STAGE_URL)
|
||||
|
||||
|
|
|
@ -4,10 +4,12 @@ from playwright_tests.pages.homepage import Homepage
|
|||
|
||||
|
||||
class AuthFlowPage(TestUtilities, AuthPage, Homepage):
|
||||
# Providing OTP code to FxA auth.
|
||||
def __provide_otp_code(self, otp_code: str):
|
||||
super().add_data_to_otp_code_input_field(otp_code)
|
||||
super().click_on_otp_code_confirm_button()
|
||||
|
||||
# Providing the needed login credentials to FxA auth.
|
||||
def __provide_login_credentials_and_submit(self, username: str, password: str):
|
||||
super().add_data_to_email_input_field(username)
|
||||
super().click_on_enter_your_email_submit_button()
|
||||
|
@ -18,6 +20,7 @@ class AuthFlowPage(TestUtilities, AuthPage, Homepage):
|
|||
super().add_data_to_password_input_field(password)
|
||||
super().click_on_enter_your_password_submit_button()
|
||||
|
||||
# Sign in flow.
|
||||
def sign_in_flow(
|
||||
self, username: str, account_password: str, sign_in_with_same_account: bool
|
||||
) -> str:
|
||||
|
|
|
@ -7,6 +7,7 @@ class MessagingSystemFlows(TestUtilities, NewMessagePage):
|
|||
def __init__(self, page: Page):
|
||||
super().__init__(page)
|
||||
|
||||
# Send message form with data flow.
|
||||
def complete_send_message_form_with_data(self, recipient_username: str, message_body: str):
|
||||
super().type_into_new_message_to_input_field(recipient_username)
|
||||
super().click_on_a_searched_user(recipient_username)
|
||||
|
|
|
@ -7,6 +7,7 @@ class EditProfileDataFlow(MyProfileEdit, TestUtilities):
|
|||
def __init__(self, page: Page):
|
||||
super().__init__(page)
|
||||
|
||||
# Editing a profile with data flow.
|
||||
def edit_profile_with_test_data(self):
|
||||
edit_test_data = super().profile_edit_test_data
|
||||
|
||||
|
@ -44,6 +45,7 @@ class EditProfileDataFlow(MyProfileEdit, TestUtilities):
|
|||
edit_test_data["valid_user_edit"]["involved_from_year"]
|
||||
)
|
||||
|
||||
# Clear all profile edit input fields flow.
|
||||
def _clear_input_fields(self):
|
||||
super().clear_all_input_fields()
|
||||
super().clear_username_field()
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
class EditQuestionPageMessages:
|
||||
EDIT_QUESTION_URL_ENDPOINT = '/edit'
|
||||
DELETE_QUESTION_URL_ENDPOINT = '/delete'
|
||||
LOCKED_THREAD_BANNER = "This thread was closed. Please ask a new question if you need help."
|
||||
ARCHIVED_THREAD_BANNER = ("This thread was archived. Please ask a new question if you need "
|
||||
"help.")
|
||||
FEED_FILE_NAME = "feed"
|
||||
MARKED_AS_SPAM_BANNER = "Marked as spam by "
|
||||
FEED_FILE_PATH = "/feed"
|
|
@ -1,2 +1,3 @@
|
|||
class FxAPageMessages:
|
||||
ACCOUNT_SETTINGS_URL = "https://accounts.firefox.com/settings"
|
||||
AUTH_PAGE_URL = "https://support.allizom.org/en-US/users/auth"
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
class ProductSolutionsMessages:
|
||||
PAGE_HEADER = " Solutions"
|
||||
CURRENT_MILESTONE_TEXT = "Explore Solutions"
|
||||
AVOID_TECH_SUPPORT_SCAMS_ARTICLE_TITLE = "Avoid and report Mozilla tech support scams"
|
||||
|
|
|
@ -4,18 +4,21 @@ from playwright_tests.core.basepage import BasePage
|
|||
|
||||
class AAQFormPage(BasePage):
|
||||
__uploaded_image_title = ""
|
||||
|
||||
# Breadcrumb locators.
|
||||
__in_progress_item_label = ("//li[@class='progress--item is-current']//span["
|
||||
"@class='progress--label']")
|
||||
# AAQ form page content locators.
|
||||
__aaq_page_logo = "//img[@class='page-heading--logo']"
|
||||
__aaq_page_product_heading = "//div[@id='main-content']/article/h3"
|
||||
__aaq_page_intro_text = "//form[@id='question-form']/p[@class='sumo-page-intro']"
|
||||
__aaq_page_info_card = "//div[contains(@class, 'info card')]"
|
||||
|
||||
# AAQ Subject
|
||||
# AAQ Subject locators.
|
||||
__aaq_subject_input_field = "//input[@id='id_title']"
|
||||
__aaq_subject_input_field_error_message = "//input[@id='id_title']/following-sibling::ul/li"
|
||||
|
||||
# Product topic dropdown
|
||||
# Product topic dropdown locators.
|
||||
__product_topic_options = "//select[@id='id_category']/option"
|
||||
__product_topic_options_without_default_none = ('//select[@id="id_category"]/option[not('
|
||||
'@value="")]')
|
||||
|
@ -23,28 +26,29 @@ class AAQFormPage(BasePage):
|
|||
__product_topic_select_dropdown_error_message = ("//select[@id='id_category']/../ul["
|
||||
"@class='errorlist']/li")
|
||||
|
||||
# Product os dropdown (Available for Mozilla VPN product only)
|
||||
# Product os dropdown locators (Available for Mozilla VPN product only).
|
||||
__product_os_select_dropdown = "//select[@id='id_os']"
|
||||
|
||||
# How can we help textarea field
|
||||
# How can we help textarea field locators.
|
||||
__how_can_we_help_textarea = "//textarea[@id='id_content']"
|
||||
__how_can_we_help_textarea_error_field = ("//textarea[@id='id_content']/../following-sibling"
|
||||
"::ul/li")
|
||||
|
||||
# Add Image
|
||||
# Add Image locators.
|
||||
__add_image_browse_button = "//span[text()='Browse...']/.."
|
||||
__uploaded_test_image_preview = f"//img[@title='{__uploaded_image_title}']"
|
||||
__uploaded_test_image_delete_button = "//form[@class='upload-input']/input[@class='delete']"
|
||||
__uploaded_image = "//a[@class='image']/img"
|
||||
|
||||
# Email me when someone answers the thread checkbox
|
||||
# Email me when someone answers the thread checkbox locators.
|
||||
__email_me_checkbox = "//input[@id='id_notifications']"
|
||||
|
||||
# form buttons
|
||||
# Form buttons locators.
|
||||
__form_submit_button = "//button[contains(text(), 'Submit')]"
|
||||
__save_edit_question_button = "//button[text()='Save Question']"
|
||||
__form_cancel_option = "//a[contains(text(),'Cancel')]"
|
||||
|
||||
# Share Data
|
||||
# Share Data locators.
|
||||
__share_data_button = "//button[@id='share-data']"
|
||||
__troubleshooting_information_textarea = "//textarea[@id='id_troubleshooting']"
|
||||
__try_these_manual_steps_link = "//p[@id='troubleshooting-manual']/a"
|
||||
|
@ -52,70 +56,50 @@ class AAQFormPage(BasePage):
|
|||
__product_version_input = "//input[@id='id_ff_version']"
|
||||
__product_os = "//input[@id='id_os']"
|
||||
|
||||
# Helfpul Tip section
|
||||
# Helpful Tip section locators.
|
||||
__helpful_tip_section = "//aside[@class='sumo-l-two-col--sidebar']/div[@class='large-only']"
|
||||
|
||||
# Learn more button
|
||||
# Learn more button locators.
|
||||
__learn_more_button = "//aside[@class='sumo-l-two-col--sidebar']//a"
|
||||
|
||||
def __init__(self, page: Page):
|
||||
super().__init__(page)
|
||||
|
||||
# Breadcrumb actions.
|
||||
def get_in_progress_item_label(self) -> str:
|
||||
return super()._get_text_of_element(self.__in_progress_item_label)
|
||||
|
||||
def get_product_image_locator(self) -> Locator:
|
||||
return super()._get_element_locator(self.__aaq_page_logo)
|
||||
def click_on_a_particular_completed_milestone(self, milestone_name: str):
|
||||
xpath = f'//span[@class="progress--label" and text()="{milestone_name}"]/../..'
|
||||
super()._click(xpath)
|
||||
|
||||
def get_aaq_form_page_heading(self) -> str:
|
||||
return super()._get_text_of_element(self.__aaq_page_product_heading)
|
||||
# Question subject actions.
|
||||
def get_value_of_subject_input_field(self) -> str:
|
||||
return super()._get_element_input_value(self.__aaq_subject_input_field)
|
||||
|
||||
def get_aaq_form_page_intro_text(self) -> str:
|
||||
return super()._get_text_of_element(self.__aaq_page_intro_text)
|
||||
|
||||
def get_aaq_form_info_card_text(self) -> str:
|
||||
return super()._get_text_of_element(self.__aaq_page_info_card)
|
||||
def clear_subject_input_field(self):
|
||||
super()._clear_field(self.__aaq_subject_input_field)
|
||||
|
||||
def get_aaq_form_subject_error(self) -> str:
|
||||
return super()._get_text_of_element(self.__aaq_subject_input_field_error_message)
|
||||
|
||||
def get_learn_more_button_locator(self) -> Locator:
|
||||
return super()._get_element_locator(self.__learn_more_button)
|
||||
def add_text_to_aaq_form_subject_field(self, text: str):
|
||||
super()._fill(self.__aaq_subject_input_field, text)
|
||||
|
||||
def get_helpful_tip_locator(self) -> Locator:
|
||||
return super()._get_element_locator(self.__helpful_tip_section)
|
||||
# Question body actions.
|
||||
def get_value_of_question_body_textarea_field(self) -> str:
|
||||
return super()._get_element_input_value(self.__how_can_we_help_textarea)
|
||||
|
||||
def get_aaq_form_topic_select_error(self) -> str:
|
||||
return super()._get_text_of_element(self.__product_topic_select_dropdown_error_message)
|
||||
|
||||
# Returns all the non-default selectable topic options.
|
||||
def get_aaq_form_topic_options(self) -> list[str]:
|
||||
return super()._get_text_of_elements(self.__product_topic_options_without_default_none)
|
||||
def clear_the_question_body_textarea_field(self):
|
||||
super()._clear_field(self.__how_can_we_help_textarea)
|
||||
|
||||
def get_aaq_form_body_error(self) -> str:
|
||||
return super()._get_text_of_element(self.__how_can_we_help_textarea_error_field)
|
||||
|
||||
def add_text_to_aaq_form_subject_field(self, text: str):
|
||||
super()._fill(self.__aaq_subject_input_field, text)
|
||||
|
||||
def add_text_to_troubleshooting_information_textarea(self, text: str):
|
||||
super()._fill(self.__troubleshooting_information_textarea, text)
|
||||
|
||||
def add_text_to_product_version_field(self, text: str):
|
||||
super()._fill(self.__product_version_input, text)
|
||||
|
||||
def add_text_to_os_field(self, text: str):
|
||||
super()._fill(self.__product_os, text)
|
||||
|
||||
def select_aaq_form_topic_value(self, value: str):
|
||||
super()._select_option_by_value(self.__product_topic_select_dropdown, value)
|
||||
|
||||
def select_aaq_form_os_value(self, value: str):
|
||||
super()._select_option_by_value(self.__product_os_select_dropdown, value)
|
||||
|
||||
def add_text_to_aaq_textarea_field(self, text: str):
|
||||
super()._fill(self.__how_can_we_help_textarea, text)
|
||||
|
||||
# Question image actions.
|
||||
def image_preview_element(self) -> ElementHandle:
|
||||
return super()._get_element_handle(self.__uploaded_test_image_preview)
|
||||
|
||||
|
@ -132,18 +116,48 @@ class AAQFormPage(BasePage):
|
|||
def get_upload_image_button_locator(self) -> Locator:
|
||||
return super()._get_element_locator(self.__add_image_browse_button)
|
||||
|
||||
def click_on_email_me_when_someone_answers_the_thread_checkbox(self):
|
||||
super()._click(self.__email_me_checkbox)
|
||||
# Page content actions.
|
||||
def get_product_image_locator(self) -> Locator:
|
||||
return super()._get_element_locator(self.__aaq_page_logo)
|
||||
|
||||
def click_on_a_particular_completed_milestone(self, milestone_name: str):
|
||||
xpath = f'//span[@class="progress--label" and text()="{milestone_name}"]/../..'
|
||||
super()._click(xpath)
|
||||
def get_aaq_form_page_heading(self) -> str:
|
||||
return super()._get_text_of_element(self.__aaq_page_product_heading)
|
||||
|
||||
def click_aaq_form_cancel_button(self):
|
||||
super()._click(self.__form_cancel_option)
|
||||
def get_aaq_form_page_intro_text(self) -> str:
|
||||
return super()._get_text_of_element(self.__aaq_page_intro_text)
|
||||
|
||||
def click_aaq_form_submit_button(self):
|
||||
super()._click(self.__form_submit_button)
|
||||
def get_aaq_form_info_card_text(self) -> str:
|
||||
return super()._get_text_of_element(self.__aaq_page_info_card)
|
||||
|
||||
def get_learn_more_button_locator(self) -> Locator:
|
||||
return super()._get_element_locator(self.__learn_more_button)
|
||||
|
||||
def get_helpful_tip_locator(self) -> Locator:
|
||||
return super()._get_element_locator(self.__helpful_tip_section)
|
||||
|
||||
# Question topic actions.
|
||||
def get_aaq_form_topic_select_error(self) -> str:
|
||||
return super()._get_text_of_element(self.__product_topic_select_dropdown_error_message)
|
||||
|
||||
# Returns all the non-default selectable topic options.
|
||||
def get_aaq_form_topic_options(self) -> list[str]:
|
||||
return super()._get_text_of_elements(self.__product_topic_options_without_default_none)
|
||||
|
||||
def select_aaq_form_topic_value(self, value: str):
|
||||
super()._select_option_by_value(self.__product_topic_select_dropdown, value)
|
||||
|
||||
def add_text_to_product_version_field(self, text: str):
|
||||
super()._fill(self.__product_version_input, text)
|
||||
|
||||
def add_text_to_os_field(self, text: str):
|
||||
super()._fill(self.__product_os, text)
|
||||
|
||||
def select_aaq_form_os_value(self, value: str):
|
||||
super()._select_option_by_value(self.__product_os_select_dropdown, value)
|
||||
|
||||
# Troubleshooting information actions.
|
||||
def add_text_to_troubleshooting_information_textarea(self, text: str):
|
||||
super()._fill(self.__troubleshooting_information_textarea, text)
|
||||
|
||||
def click_on_learn_more_button(self):
|
||||
super()._click(self.__learn_more_button)
|
||||
|
@ -156,3 +170,17 @@ class AAQFormPage(BasePage):
|
|||
|
||||
def click_on_try_these_manual_steps_link(self):
|
||||
super()._click(self.__try_these_manual_steps_link)
|
||||
|
||||
# Email me when someone answers the thread section actions.
|
||||
def click_on_email_me_when_someone_answers_the_thread_checkbox(self):
|
||||
super()._click(self.__email_me_checkbox)
|
||||
|
||||
def click_aaq_form_cancel_button(self):
|
||||
super()._click(self.__form_cancel_option)
|
||||
|
||||
def click_aaq_form_submit_button(self):
|
||||
super()._click(self.__form_submit_button)
|
||||
|
||||
# Edit question form actions.
|
||||
def click_aaq_edit_submit_button(self):
|
||||
super()._click(self.__save_edit_question_button)
|
||||
|
|
|
@ -3,16 +3,19 @@ from playwright_tests.core.basepage import BasePage
|
|||
|
||||
|
||||
class KBArticlePage(BasePage):
|
||||
# KB article page content locators.
|
||||
__kb_article_heading = "//h1[@class='sumo-page-heading']"
|
||||
|
||||
# Editing Tools options
|
||||
# Editing Tools options locators.
|
||||
__editing_tools_show_history_option = "//a[contains(text(), 'Show History')]"
|
||||
|
||||
def __init__(self, page: Page):
|
||||
super().__init__(page)
|
||||
|
||||
# KB Article page content actions.
|
||||
def get_text_of_article_title(self) -> str:
|
||||
return super()._get_text_of_element(self.__kb_article_heading)
|
||||
|
||||
# KB Article editing tools section actions.
|
||||
def click_on_show_history_option(self):
|
||||
super()._click(self.__editing_tools_show_history_option)
|
||||
|
|
|
@ -3,6 +3,7 @@ from playwright_tests.core.basepage import BasePage
|
|||
|
||||
|
||||
class KBArticleShowHistoryPage(BasePage):
|
||||
# Show History delete document section locators.
|
||||
__delete_this_document_button = "//div[@id='delete-doc']/a"
|
||||
__delete_this_document_confirmation_delete_button = "//div[@class='submit']/input"
|
||||
__delete_this_document_confirmation_cancel_button = "//div[@class='submit']/a"
|
||||
|
@ -11,6 +12,7 @@ class KBArticleShowHistoryPage(BasePage):
|
|||
def __init__(self, page: Page):
|
||||
super().__init__(page)
|
||||
|
||||
# Delete document actions.
|
||||
def click_on_delete_this_document_button(self):
|
||||
super()._click(self.__delete_this_document_button)
|
||||
|
||||
|
|
|
@ -4,6 +4,7 @@ from playwright_tests.core.basepage import BasePage
|
|||
|
||||
class SubmitKBArticlePage(BasePage):
|
||||
__kb_article_for_contributors_sidebar = "//nav[@id='for-contributors-sidebar']"
|
||||
# New KB article form locators.
|
||||
__kb_article_form_title = "//input[@id='id_title']"
|
||||
__kb_article_form_slug = "//input[@id='id_slug']"
|
||||
__kb_article_category_select = "//select[@id='id_category']"
|
||||
|
@ -12,7 +13,7 @@ class SubmitKBArticlePage(BasePage):
|
|||
__kb_article_search_for_related_documents = "//input[@id='search-related']"
|
||||
__kb_article_keywords_input = "//input[@id='id_keywords']"
|
||||
__kb_article_search_result_summary_textarea = "//textarea[@id='id_summary']"
|
||||
# try
|
||||
# New KB article content locators.
|
||||
__kb_article_content_textarea = "//textarea[@id='id_content'][1]"
|
||||
__kb_article_insert_media = "//button[contains(@class, 'btn-media')]"
|
||||
__kb_article_insert_media_modal_images = "//div[@id='media-modal']//img"
|
||||
|
@ -32,9 +33,11 @@ class SubmitKBArticlePage(BasePage):
|
|||
def __init__(self, page: Page):
|
||||
super().__init__(page)
|
||||
|
||||
# For Contributors side navbar actions.
|
||||
def for_contributors_section(self) -> Locator:
|
||||
return super()._get_element_locator(self.__kb_article_for_contributors_sidebar)
|
||||
|
||||
# New KB form actions.
|
||||
def add_text_to_article_form_title_field(self, text: str):
|
||||
super()._fill(self.__kb_article_form_title, text)
|
||||
|
||||
|
|
|
@ -3,25 +3,35 @@ from playwright_tests.core.basepage import BasePage
|
|||
|
||||
|
||||
class ContactSupportPage(BasePage):
|
||||
# Breadcrumb locators.
|
||||
__current_milestone = ("//li[@class='progress--item is-current']//span["
|
||||
"@class='progress--label']")
|
||||
# Page content locators.
|
||||
__page_main_heading = "//h1[@class='sumo-page-heading']"
|
||||
__page_subheading = "//h2[@class='sumo-page-subheading']"
|
||||
__browse_all_product_forums_button = "//a[contains(text(), 'Browse All Product Forums')]"
|
||||
|
||||
# Product Card Titles locators.
|
||||
__product_cards_titles = "//div[@id='product-picker']//h3[@class='card--title']"
|
||||
|
||||
def __init__(self, page: Page):
|
||||
super().__init__(page)
|
||||
|
||||
# Breadcrumb related actions.
|
||||
def _get_text_of_current_milestone(self) -> str:
|
||||
return super()._get_text_of_element(self.__current_milestone)
|
||||
|
||||
# Page actions.
|
||||
def _get_contact_support_main_heading(self) -> str:
|
||||
return super()._get_text_of_element(self.__page_main_heading)
|
||||
|
||||
def _get_contact_support_subheading_text(self) -> str:
|
||||
return super()._get_text_of_element(self.__page_subheading)
|
||||
|
||||
def _click_on_browse_all_product_forums_button(self):
|
||||
super()._click(self.__browse_all_product_forums_button)
|
||||
|
||||
# Product card actions.
|
||||
def _get_all_product_card_titles(self) -> list[str]:
|
||||
return super()._get_text_of_elements(self.__product_cards_titles)
|
||||
|
||||
|
@ -30,9 +40,6 @@ class ContactSupportPage(BasePage):
|
|||
f"@class='card--desc']")
|
||||
return super()._get_text_of_element(xpath)
|
||||
|
||||
def _click_on_browse_all_product_forums_button(self):
|
||||
super()._click(self.__browse_all_product_forums_button)
|
||||
|
||||
def _click_on_a_particular_card(self, card_name: str):
|
||||
xpath = f"//h3[@class='card--title']/a[@data-event-label='{card_name}']"
|
||||
super()._click(xpath)
|
||||
|
|
|
@ -0,0 +1,52 @@
|
|||
from playwright.sync_api import Page
|
||||
from playwright_tests.core.basepage import BasePage
|
||||
|
||||
|
||||
class ProductSupportForum(BasePage):
|
||||
# Ask the Community button
|
||||
__ask_the_community_button = "//a[contains(text() ,'Ask the Community')]"
|
||||
|
||||
# Showing questions tagged section
|
||||
__showing_questions_tagged_tag = "//div[@id='tagged']//a[@class='tag']"
|
||||
__show_all_questions_option = "//a[@class='show-all']"
|
||||
|
||||
# Question status filters
|
||||
__all_question_status_filters = "//ul[@class='tabs--list subtopics']/li[@class='tabs--item']"
|
||||
|
||||
# Side navbar filter options
|
||||
__side_navbar_filter_options = "//ul[@class='sidebar-nav--list']//a"
|
||||
|
||||
# Question list
|
||||
__all_question_list_tags = "//li[@class='tag']"
|
||||
__all_listed_articles = "//div[@id='questions-list']//article"
|
||||
|
||||
def __init__(self, page: Page):
|
||||
super().__init__(page)
|
||||
|
||||
# Ask the Community actions
|
||||
def _click_on_the_ask_the_community_button(self):
|
||||
super()._click(self.__ask_the_community_button)
|
||||
|
||||
# Showing Questions Tagged section actions
|
||||
def _get_text_of_selected_tag_filter_option(self) -> str:
|
||||
return super()._get_text_of_element(self.__showing_questions_tagged_tag)
|
||||
|
||||
def _click_on_the_show_all_questions_option(self):
|
||||
super()._click(self.__show_all_questions_option)
|
||||
|
||||
# Question list actions
|
||||
def _get_all_question_list_tags(self, question_id: str) -> list[str]:
|
||||
xpath = f"//article[@id='{question_id}']//li[@class='tag']"
|
||||
question_tags = super()._get_text_of_elements(xpath)
|
||||
return question_tags
|
||||
|
||||
def _extract_question_ids(self) -> list[str]:
|
||||
elements = super()._get_elements_locators(self.__all_listed_articles)
|
||||
id_values = []
|
||||
for element in elements:
|
||||
id_values.append(
|
||||
super()._get_element_locator_attribute_value(
|
||||
locator=element, attribute="id"
|
||||
)
|
||||
)
|
||||
return id_values
|
|
@ -3,6 +3,7 @@ from playwright_tests.core.basepage import BasePage
|
|||
|
||||
|
||||
class SupportForumsPage(BasePage):
|
||||
# Support forum page locators.
|
||||
__page_main_heading = "//h1[@class='sumo-page-heading']"
|
||||
__page_intro = "//p[@class='sumo-page-intro']"
|
||||
__product_card_titles = "//h3[@class='card--title']"
|
||||
|
@ -11,22 +12,24 @@ class SupportForumsPage(BasePage):
|
|||
def __init__(self, page: Page):
|
||||
super().__init__(page)
|
||||
|
||||
# Page content actions.
|
||||
def _get_page_heading_text(self) -> str:
|
||||
return super()._get_text_of_element(self.__page_main_heading)
|
||||
|
||||
def _get_page_intro_text(self) -> str:
|
||||
return super()._get_text_of_element(self.__page_intro)
|
||||
|
||||
def _click_on_all_products_support_forum_button(self):
|
||||
super()._click(self.__all_products_support_forum_button)
|
||||
|
||||
# Product cards actions.
|
||||
def _click_on_a_particular_product_card(self, card_name: str):
|
||||
xpath = f"//strong[text()='{card_name}']"
|
||||
super()._click(xpath)
|
||||
|
||||
def _get_product_card_titles_list(self) -> list[str]:
|
||||
return super()._get_text_of_elements(self.__product_card_titles)
|
||||
|
||||
def _get_card_description_text(self, card_title: str) -> str:
|
||||
xpath = f"//strong[text()='{card_title}']/../../following-sibling::p"
|
||||
return super()._get_text_of_element(xpath)
|
||||
|
||||
def _click_on_all_products_support_forum_button(self):
|
||||
super()._click(self.__all_products_support_forum_button)
|
||||
|
||||
def _click_on_a_particular_product_card(self, card_name: str):
|
||||
xpath = f"//strong[text()='{card_name}']"
|
||||
super()._click(xpath)
|
||||
|
|
|
@ -1,64 +1,93 @@
|
|||
from playwright.sync_api import Page, ElementHandle
|
||||
from playwright.sync_api import Page, ElementHandle, Locator
|
||||
from playwright_tests.core.basepage import BasePage
|
||||
|
||||
|
||||
class ProductSolutionsPage(BasePage):
|
||||
# Page breadcrumb locators.
|
||||
__complete_progress_item = "//li[@class='progress--item is-complete']/a"
|
||||
__complete_progress_item_label = ("//li[@class='progress--item is-complete']//span["
|
||||
"@class='progress--label']")
|
||||
__current_progress_item_label = ("//li[@class='progress--item is-current']//span["
|
||||
"@class='progress--label']")
|
||||
# Page content locators.
|
||||
__product_title_heading = "//span[@class='product-title-text']"
|
||||
__page_heading_intro_text = "//p[@class='page-heading--intro-text']"
|
||||
|
||||
# Find help locators.
|
||||
__product_solutions_find_help_searchbar = "//form[@id='question-search-masthead']/input"
|
||||
__product_solutions_find_help_search_button = "//form[@id='question-search-masthead']/button"
|
||||
__page_heading_intro_text = "//p[@class='page-heading--intro-text']"
|
||||
|
||||
# Still need help locators.
|
||||
__still_need_help_subheading = "//div[contains(@class, 'aaq-widget')]/p"
|
||||
__still_need_help_ask_now_button = "//a[@data-event-action='aaq']"
|
||||
|
||||
# Featured articles locators.
|
||||
__featured_article_section_title = "//h2[contains(text(),'Featured Articles')]"
|
||||
__featured_articles_cards = "//h2[contains(text(),'Featured Articles')]/../..//a"
|
||||
|
||||
# Popular topics locators.
|
||||
__popular_topics_section_title = "//h2[contains(text(),'Popular Topics')]"
|
||||
__popular_topics_cards = "//h2[contains(text(),'Popular Topics')]/../..//a"
|
||||
|
||||
# Support scam banner locators.
|
||||
__support_scams_banner = "//div[@id='id_scam_alert']"
|
||||
__support_scam_banner_learn_more_button = "//div[@id='id_scam_alert']//a"
|
||||
|
||||
def __init__(self, page: Page):
|
||||
super().__init__(page)
|
||||
|
||||
# Still need help actions.
|
||||
def _click_ask_now_button(self):
|
||||
super()._click(self.__still_need_help_ask_now_button)
|
||||
|
||||
def _click_on_the_completed_milestone(self):
|
||||
super()._click(self.__complete_progress_item)
|
||||
|
||||
def _click_on_a_featured_article_card(self, card_name: str):
|
||||
xpath = f'//h2[contains(text(),"Featured Articles")]/../..//a[text()="{card_name}"]'
|
||||
super()._click(xpath)
|
||||
|
||||
def _click_on_a_popular_topic_card(self, card_name: str):
|
||||
xpth = f'//h2[contains(text(),"Popular Topics")]/../..//a[@data-event-label="{card_name}"]'
|
||||
super()._click(xpth)
|
||||
|
||||
def _get_current_milestone_text(self) -> str:
|
||||
return super()._get_text_of_element(self.__current_progress_item_label)
|
||||
|
||||
def _get_product_solutions_heading(self) -> str:
|
||||
return super()._get_text_of_element(self.__product_title_heading)
|
||||
|
||||
def _get_aaq_subheading_text(self) -> str:
|
||||
return super()._get_text_of_element(self.__still_need_help_subheading)
|
||||
|
||||
def _get_all_featured_articles_titles(self) -> list[str]:
|
||||
return super()._get_text_of_elements(self.__featured_articles_cards)
|
||||
|
||||
def _get_aaq_widget_button_name(self) -> str:
|
||||
return super()._get_text_of_element(self.__still_need_help_ask_now_button)
|
||||
|
||||
def _get_popular_topics(self) -> list[str]:
|
||||
return super()._get_text_of_elements(self.__popular_topics_cards)
|
||||
def get_still_need_help_locator(self) -> Locator:
|
||||
return super()._get_element_locator(self.__still_need_help_ask_now_button)
|
||||
|
||||
def _is_product_solutions_page_header_displayed(self) -> ElementHandle:
|
||||
return super()._get_element_handle(self.__product_title_heading)
|
||||
# Breadcrumb actions.
|
||||
def _click_on_the_completed_milestone(self):
|
||||
super()._click(self.__complete_progress_item)
|
||||
|
||||
def _get_current_milestone_text(self) -> str:
|
||||
return super()._get_text_of_element(self.__current_progress_item_label)
|
||||
|
||||
# Featured article actions.
|
||||
def _click_on_a_featured_article_card(self, card_name: str):
|
||||
xpath = f'//h2[contains(text(),"Featured Articles")]/../..//a[text()="{card_name}"]'
|
||||
super()._click(xpath)
|
||||
|
||||
def _get_all_featured_articles_titles(self) -> list[str]:
|
||||
return super()._get_text_of_elements(self.__featured_articles_cards)
|
||||
|
||||
def _is_featured_article_section_displayed(self) -> bool:
|
||||
return super()._is_element_visible(self.__featured_article_section_title)
|
||||
|
||||
# Popular topic actions.
|
||||
def _click_on_a_popular_topic_card(self, card_name: str):
|
||||
xpth = f'//h2[contains(text(),"Popular Topics")]/../..//a[@data-event-label="{card_name}"]'
|
||||
super()._click(xpth)
|
||||
|
||||
def _get_popular_topics(self) -> list[str]:
|
||||
return super()._get_text_of_elements(self.__popular_topics_cards)
|
||||
|
||||
def _is_popular_topics_section_displayed(self) -> bool:
|
||||
return super()._is_element_visible(self.__popular_topics_section_title)
|
||||
|
||||
# Product solutions actions.
|
||||
def _get_product_solutions_heading(self) -> str:
|
||||
return super()._get_text_of_element(self.__product_title_heading)
|
||||
|
||||
def _is_product_solutions_page_header_displayed(self) -> ElementHandle:
|
||||
return super()._get_element_handle(self.__product_title_heading)
|
||||
|
||||
# Support scam banner actions
|
||||
def _click_on_scam_alert_banner_learn_more(self):
|
||||
super()._click(self.__support_scam_banner_learn_more_button)
|
||||
|
||||
def get_scam_banner_locator(self) -> Locator:
|
||||
return super()._get_element_locator(self.__support_scams_banner)
|
||||
|
|
|
@ -3,39 +3,50 @@ from playwright_tests.core.basepage import BasePage
|
|||
|
||||
|
||||
class ProductTopicPage(BasePage):
|
||||
# Product topic page content locators.
|
||||
__page_title = "//h1[@class='topic-title sumo-page-heading']"
|
||||
__page_subheading = "//div[@class='sumo-article-header--text']/p"
|
||||
|
||||
# Product topic page navbar locators.
|
||||
__navbar_links = "//a[@data-event-action='topic sidebar']"
|
||||
__selected_nav_link = "//a[contains(@class,'selected')]"
|
||||
|
||||
# Product topic page learn more locators.
|
||||
__learn_more_button = "//section[@id='get-involved-button']//a"
|
||||
|
||||
# Product topic page still need help locators.
|
||||
__still_need_help_subheading = "//div[contains(@class, 'aaq-widget')]/p"
|
||||
__aaq_button = "//a[@data-event-label='aaq widget']"
|
||||
|
||||
def __init__(self, page: Page):
|
||||
super().__init__(page)
|
||||
|
||||
# Page content actions.
|
||||
def _get_page_title(self) -> str:
|
||||
return super()._get_text_of_element(self.__page_title)
|
||||
|
||||
# Navbar actions.
|
||||
def _get_selected_navbar_option(self) -> str:
|
||||
return super()._get_text_of_element(self.__selected_nav_link)
|
||||
|
||||
def _get_navbar_links_text(self) -> list[str]:
|
||||
return super()._get_text_of_elements(self.__navbar_links)
|
||||
|
||||
def _get_aaq_subheading_text(self) -> str:
|
||||
return super()._get_text_of_element(self.__still_need_help_subheading)
|
||||
|
||||
def _click_on_a_navbar_option(self, option_name: str):
|
||||
xpath = f'//a[@data-event-action="topic sidebar" and contains(text(), "{option_name}")]'
|
||||
super()._click(xpath)
|
||||
|
||||
def _click_on_aaq_button(self):
|
||||
super()._click(self.__aaq_button)
|
||||
|
||||
def _click_on_learn_more_button(self):
|
||||
super()._click(self.__learn_more_button)
|
||||
def _get_navbar_links_text(self) -> list[str]:
|
||||
return super()._get_text_of_elements(self.__navbar_links)
|
||||
|
||||
def _get_navbar_option_link(self, option_name: str) -> str:
|
||||
xpath = f'//a[@data-event-action="topic sidebar" and contains(text(), "{option_name}")]'
|
||||
return super()._get_element_attribute_value(xpath, "href")
|
||||
|
||||
# AAQ section actions.
|
||||
def _get_aaq_subheading_text(self) -> str:
|
||||
return super()._get_text_of_element(self.__still_need_help_subheading)
|
||||
|
||||
def _click_on_aaq_button(self):
|
||||
super()._click(self.__aaq_button)
|
||||
|
||||
# Learn more section actions.
|
||||
def _click_on_learn_more_button(self):
|
||||
super()._click(self.__learn_more_button)
|
||||
|
|
|
@ -14,6 +14,7 @@ from playwright_tests.pages.contact_support_pages.contact_support_page import Co
|
|||
from playwright_tests.pages.contribute_pages.contribute_page import ContributePage
|
||||
from playwright_tests.pages.contribute_pages.ways_to_contribute_pages import WaysToContributePages
|
||||
from playwright_tests.pages.footer import FooterSection
|
||||
from playwright_tests.pages.forums_pages.product_support_forum import ProductSupportForum
|
||||
from playwright_tests.pages.forums_pages.support_forums_page import SupportForumsPage
|
||||
from playwright_tests.pages.homepage import Homepage
|
||||
from playwright_tests.pages.messaging_system_pages.inbox_page import InboxPage
|
||||
|
@ -97,6 +98,7 @@ class SumoPages:
|
|||
|
||||
# Forums
|
||||
self.support_forums_page = SupportForumsPage(page)
|
||||
self.product_support_forum = ProductSupportForum(page)
|
||||
|
||||
# Auth flow Page.
|
||||
self.auth_flow_page = AuthFlowPage(page)
|
||||
|
|
|
@ -8,16 +8,26 @@ class QuestionPage(BasePage):
|
|||
__posted_questions_success_banner_my_questions_link = "//ul[@class='user-messages']/li/p/a"
|
||||
__posted_questions_success_banner_close_button = "//ul[@class='user-messages']/li/button"
|
||||
|
||||
# Lock this thread banner
|
||||
__lock_this_thread_banner = "//div[@class='notice mzp-c-notification-bar mzp-t-click']/p"
|
||||
__lock_this_thread_banner_link = ("//div[@class='notice mzp-c-notification-bar "
|
||||
"mzp-t-click']/p/a")
|
||||
|
||||
# Marked as spam banner
|
||||
__marked_as_spam_banner = "//p[@class='is-spam']"
|
||||
|
||||
# Question
|
||||
__question_author = "//div[@class='question']//span[@class='display-name']"
|
||||
__questions_header = "//article//h2"
|
||||
__questions_header = "//h2[@class='sumo-callout-heading summary no-product-heading']"
|
||||
__question_body = "//div[@class='main-content']/div/p"
|
||||
__modified_question_section = "//p[@class='edited text-body-sm']"
|
||||
|
||||
# Progress bar
|
||||
__complete_progress_items_label = ("//li[@class='progress--item is-complete']//span["
|
||||
"@class='progress--label']")
|
||||
|
||||
# Breadcrumbs
|
||||
__aaq_page_breadcrumbs = "//ol[@id='breadcrumbs']/li"
|
||||
__aaq_page_breadcrumbs = "//ol[@id='breadcrumbs']/li/a"
|
||||
|
||||
# Question details
|
||||
__question_details_button = "//button[@aria-controls='question-details']"
|
||||
|
@ -37,10 +47,15 @@ class QuestionPage(BasePage):
|
|||
__stop_email_updates_option = "//ul[@id='related-content']/li[@class='email']/a"
|
||||
__subscribe_to_feed_option = "//ul[@id='related-content']/li[@class='rss']/a"
|
||||
__delete_this_question_option = "//ul[@id='related-content']//a[@class='delete']"
|
||||
__lock_this_question_option = "//a[@data-form='lock-form']"
|
||||
__archive_this_question_option = "//a[@data-form='archive-form']"
|
||||
__system_details_options = "//div[@id='system-details']/ul[@class='system']/li"
|
||||
__mark_as_spam_option = "//ul[@id='related-content']//form[@class='spam-form cf']/a"
|
||||
|
||||
# Tags section
|
||||
__question_tags_options = "//li[@class='tag']/a"
|
||||
__add_a_tag_input_field = "//input[@id='id_tag_input']"
|
||||
__add_a_tab_button = "//form[@class='tag-adder']/input[@type='submit']"
|
||||
|
||||
# Post a reply section
|
||||
__post_a_reply_section_heading = "//h3[@class='sumo-card-heading']"
|
||||
|
@ -54,9 +69,12 @@ class QuestionPage(BasePage):
|
|||
|
||||
# Needs more information from the user
|
||||
__needs_more_information_from_the_user_checkbox = "//input[@id='id_needs_info']"
|
||||
__more_information_panel_header = ("//section[@id='more-system-details']//h3[contains(text(),"
|
||||
"'More Information')]")
|
||||
|
||||
# Attached image
|
||||
__attached_image = "//a[@class='image']/img"
|
||||
__add_image_button = "//div[@class='field add-attachment']"
|
||||
|
||||
# Preview Reply button
|
||||
__preview_reply_button = "//input[@id='preview']"
|
||||
|
@ -71,37 +89,36 @@ class QuestionPage(BasePage):
|
|||
def __init__(self, page: Page):
|
||||
super().__init__(page)
|
||||
|
||||
# Breadcrumbs actions.
|
||||
def get_current_breadcrumb_locator(self, question_title: str) -> Locator:
|
||||
xpath = f"//ol[@id='breadcrumbs']/li[text()='{question_title}']"
|
||||
return super()._get_element_locator(xpath)
|
||||
|
||||
def click_on_breadcrumb_locator(self, element: Locator):
|
||||
super()._click(element)
|
||||
|
||||
# Get email updates actions.
|
||||
def get_email_updates_option(self) -> Locator:
|
||||
return super()._get_element_locator(self.__stop_email_updates_option)
|
||||
|
||||
# Page content actions.
|
||||
def get_question_header(self) -> str:
|
||||
return super()._get_text_of_element(self.__questions_header)
|
||||
|
||||
def get_question_body(self) -> str:
|
||||
return super()._get_text_of_element(self.__question_body)
|
||||
|
||||
def get_question_author_name(self) -> str:
|
||||
return super()._get_text_of_element(self.__question_author)
|
||||
|
||||
def get_question_tag_options(self) -> list[str]:
|
||||
return super()._get_text_of_elements(self.__question_tags_options)
|
||||
def get_modified_question_locator(self) -> Locator:
|
||||
return super()._get_element_locator(self.__modified_question_section)
|
||||
|
||||
def get_attached_image(self) -> Locator:
|
||||
return super()._get_element_locator(self.__attached_image)
|
||||
def get_modified_by_text(self) -> str:
|
||||
return super()._get_text_of_element(self.__modified_question_section)
|
||||
|
||||
def get_more_information_with_text_locator(self, text: str) -> Locator:
|
||||
xpath = f"//div[@class='about-support']/p[text()='{text}']"
|
||||
return super()._get_element_locator(xpath)
|
||||
|
||||
def get_user_agent_information(self) -> str:
|
||||
return super()._get_text_of_element(self.__user_agent_information)
|
||||
|
||||
def add_text_to_post_a_reply_textarea(self, text: str):
|
||||
super()._fill(self.__post_a_reply_textarea, text)
|
||||
|
||||
def get_system_details_information(self) -> list[str]:
|
||||
return super()._get_text_of_elements(self.__system_details_options)
|
||||
|
||||
def click_on_post_reply_button(self, repliant_username) -> str:
|
||||
xpath_display_name = \
|
||||
f"//span[@class='display-name' and contains(text(), '{repliant_username}')]"
|
||||
|
||||
xpath_reply_id = (f"//span[@class='display-name' and contains(text(), "
|
||||
f"'{repliant_username}')]/ancestor::div[@class='answer ']")
|
||||
super()._click(self.__post_reply_button)
|
||||
super()._wait_for_selector(xpath_display_name)
|
||||
return super()._get_element_attribute_value(xpath_reply_id, "id")
|
||||
def get_add_image_section_locator(self) -> Locator:
|
||||
return super()._get_element_locator(self.__add_image_button)
|
||||
|
||||
def click_on_my_questions_banner_option(self):
|
||||
super()._click(self.__posted_questions_success_banner_my_questions_link)
|
||||
|
@ -119,11 +136,62 @@ class QuestionPage(BasePage):
|
|||
xpath = f"//div[@id='{reply_id}']//a[@class='author-name']"
|
||||
super()._click(xpath)
|
||||
|
||||
def click_delete_this_question_question_tools_option(self):
|
||||
super()._click(self.__delete_this_question_option)
|
||||
# Question tag actions.
|
||||
def get_question_tag_options(self) -> list[str]:
|
||||
return super()._get_text_of_elements(self.__question_tags_options)
|
||||
|
||||
def click_delete_this_question_button(self):
|
||||
super()._click(self.__delete_question_delete_button)
|
||||
def get_remove_tag_button_locator(self, tag_name: str) -> Locator:
|
||||
xpath = xpath = (f"//ul[@class='tag-list cf']//a[text()='{tag_name}']/following-sibling"
|
||||
f"::button[@class='remover']")
|
||||
return super()._get_element_locator(xpath)
|
||||
|
||||
def add_text_to_add_a_tag_input_field(self, text: str):
|
||||
super()._fill(self.__add_a_tag_input_field, text)
|
||||
dropdown_xpath = f"//li[@class='ui-menu-item']/div[text()='{text}']"
|
||||
super()._click(dropdown_xpath)
|
||||
|
||||
def get_add_a_tag_input_field(self) -> Locator:
|
||||
return super()._get_element_locator(self.__add_a_tag_input_field)
|
||||
|
||||
def get_add_a_tag_button(self) -> Locator:
|
||||
return super()._get_element_locator(self.__add_a_tab_button)
|
||||
|
||||
def click_on_add_a_tag_button(self):
|
||||
super()._click(self.__add_a_tab_button)
|
||||
|
||||
def click_on_a_certain_tag(self, tag_name: str):
|
||||
xpath = f"//li[@class='tag']//a[text()='{tag_name}']"
|
||||
super()._click(xpath)
|
||||
|
||||
def get_a_certain_tag(self, tag_name: str) -> Locator:
|
||||
xpath = f"//li[@class='tag']//a[text()='{tag_name}']"
|
||||
return super()._get_element_locator(xpath)
|
||||
|
||||
def click_on_tag_remove_button(self, tag_name: str):
|
||||
xpath = (f"//li[@class='tag']//a[text()='{tag_name}']/following-sibling::button["
|
||||
f"@class='remover']")
|
||||
super()._click(xpath)
|
||||
|
||||
# Attached image actions.
|
||||
def get_attached_image(self) -> Locator:
|
||||
return super()._get_element_locator(self.__attached_image)
|
||||
|
||||
# Question more information actions.
|
||||
def get_more_information_with_text_locator(self, text: str) -> Locator:
|
||||
xpath = f"//div[@class='about-support']/p[text()='{text}']"
|
||||
return super()._get_element_locator(xpath)
|
||||
|
||||
def get_question_details_button_locator(self) -> Locator:
|
||||
return super()._get_element_locator(self.__question_details_button)
|
||||
|
||||
def get_more_information_locator(self) -> Locator:
|
||||
return super()._get_element_locator(self.__more_information_panel_header)
|
||||
|
||||
def get_user_agent_information(self) -> str:
|
||||
return super()._get_text_of_element(self.__user_agent_information)
|
||||
|
||||
def get_system_details_information(self) -> list[str]:
|
||||
return super()._get_text_of_elements(self.__system_details_options)
|
||||
|
||||
def click_on_question_details_button(self):
|
||||
super()._click(self.__question_details_button)
|
||||
|
@ -133,3 +201,80 @@ class QuestionPage(BasePage):
|
|||
|
||||
def click_on_the_additional_system_panel_close_button(self):
|
||||
super()._click(self.__close_additional_system_details_button)
|
||||
|
||||
# Post a reply actions.
|
||||
def add_text_to_post_a_reply_textarea(self, text: str):
|
||||
super()._fill(self.__post_a_reply_textarea, text)
|
||||
|
||||
def get_post_a_reply_textarea_locator(self) -> Locator:
|
||||
return super()._get_element_locator(self.__post_a_reply_textarea)
|
||||
|
||||
def get_posted_reply_locator(self, question_id: str) -> Locator:
|
||||
xpath = f"//div[@id='{question_id}']"
|
||||
return super()._get_element_locator(xpath)
|
||||
|
||||
def click_on_post_reply_button(self, repliant_username) -> str:
|
||||
xpath_display_name = \
|
||||
f"//span[@class='display-name' and contains(text(), '{repliant_username}')]"
|
||||
|
||||
xpath_reply_id = (f"//span[@class='display-name' and contains(text(), "
|
||||
f"'{repliant_username}')]/ancestor::div[@class='answer ']")
|
||||
super()._click(self.__post_reply_button)
|
||||
super()._wait_for_selector(xpath_display_name)
|
||||
return super()._get_element_attribute_value(xpath_reply_id, "id")
|
||||
|
||||
# Question Tools actions.
|
||||
def get_edit_this_question_option_locator(self) -> Locator:
|
||||
return super()._get_element_locator(self.__edit_this_question_option)
|
||||
|
||||
def get_delete_this_question_locator(self) -> Locator:
|
||||
return super()._get_element_locator(self.__delete_this_question_option)
|
||||
|
||||
def get_lock_this_question_locator(self) -> Locator:
|
||||
return super()._get_element_locator(self.__lock_this_question_option)
|
||||
|
||||
# Stands for archived banner as well
|
||||
def get_thread_locked_text(self) -> str:
|
||||
return super()._get_text_of_element(self.__lock_this_thread_banner)
|
||||
|
||||
def get_thread_locked_locator(self) -> Locator:
|
||||
return super()._get_element_locator(self.__lock_this_thread_banner)
|
||||
|
||||
def get_archive_this_question_locator(self) -> Locator:
|
||||
return super()._get_element_locator(self.__archive_this_question_option)
|
||||
|
||||
def get_needs_more_information_checkbox_locator(self) -> Locator:
|
||||
return super()._get_element_locator(self.__needs_more_information_from_the_user_checkbox)
|
||||
|
||||
def get_mark_as_spam_locator(self) -> Locator:
|
||||
return super()._get_element_locator(self.__mark_as_spam_option)
|
||||
|
||||
def get_marked_as_spam_banner_locator(self) -> Locator:
|
||||
return super()._get_element_locator(self.__marked_as_spam_banner)
|
||||
|
||||
def get_marked_as_spam_banner_text(self) -> str:
|
||||
return super()._get_text_of_element(self.__marked_as_spam_banner)
|
||||
|
||||
def click_on_thread_locked_link(self):
|
||||
super()._click(self.__lock_this_thread_banner_link)
|
||||
|
||||
def click_on_lock_this_question_locator(self):
|
||||
super()._click(self.__lock_this_question_option)
|
||||
|
||||
def click_on_subscribe_to_feed_option(self):
|
||||
super()._click(self.__subscribe_to_feed_option)
|
||||
|
||||
def click_on_mark_as_spam_option(self):
|
||||
super()._click(self.__mark_as_spam_option)
|
||||
|
||||
def click_on_edit_this_question_question_tools_option(self):
|
||||
super()._click(self.__edit_this_question_option)
|
||||
|
||||
def click_delete_this_question_question_tools_option(self):
|
||||
super()._click(self.__delete_this_question_option)
|
||||
|
||||
def click_on_archive_this_question_option(self):
|
||||
super()._click(self.__archive_this_question_option)
|
||||
|
||||
def click_delete_this_question_button(self):
|
||||
super()._click(self.__delete_question_delete_button)
|
||||
|
|
|
@ -15,3 +15,4 @@ markers =
|
|||
productSolutionsPage: Tests belonging to the product solutions page.
|
||||
productTopicsPage: Tests belonging to the product topics page.
|
||||
aaqPage: Tests belonging to the AAQ page.
|
||||
postedQuestions: Tests belonging to the posted question page.
|
||||
|
|
|
@ -1,10 +1,15 @@
|
|||
{
|
||||
"valid_firefox_question": {
|
||||
"subject": "Test Question ",
|
||||
"subject_updated": "Test Question Updated",
|
||||
"topic_value": "bookmarks",
|
||||
"question_body": "'''Lorem ipsum''' dolor ''sit amet'', consectetur [https://www.mediafax.ro adipiscing] elit, [[Stage test owl|sed]] do eiusmod tempor incididunt ut labore et dolore magna aliqua. Tincidunt id aliquet risus feugiat in ante. Etiam non quam lacus suspendisse faucibus interdum posuere. Diam sollicitudin tempor id eu nisl nunc mi ipsum. Velit egestas dui id ornare arcu odio ut sem nulla. Risus nec feugiat in fermentum posuere urna nec tincidunt. Sed egestas egestas fringilla phasellus faucibus. Amet consectetur adipiscing elit duis tristique. Lorem mollis aliquam ut porttitor. Purus sit amet volutpat consequat mauris. Lobortis mattis aliquam faucibus purus in. Enim praesent elementum facilisis leo vel. Volutpat lacus laoreet non curabitur gravida arcu. Tempus iaculis urna id volutpat.",
|
||||
"body_updated": "Updated body",
|
||||
"simple_body_text": "Body content test",
|
||||
"image_name": "test.image.jpg",
|
||||
"image_path": "test_data/test-image.png"
|
||||
"image_path": "test_data/test-image.png",
|
||||
"question_reply": "Test reply to question",
|
||||
"custom_tag": "test"
|
||||
},
|
||||
"troubleshooting_information_kb_article_url": "https://support.mozilla.org/en-US/kb/use-troubleshooting-information-page-fix-firefox",
|
||||
"troubleshooting_information_textarea_field": "Test Troubleshooting data",
|
||||
|
|
|
@ -8,6 +8,8 @@ from playwright_tests.messages.contact_support_page_messages.contact_support_mes
|
|||
ContactSupportMessages)
|
||||
from playwright_tests.messages.contribute_pages_messages.con_page_messages import (
|
||||
ContributePageMessages)
|
||||
from playwright_tests.messages.product_solutions_page_messages.product_solutions_messages import \
|
||||
ProductSolutionsMessages
|
||||
|
||||
|
||||
class TestAAQPage(TestUtilities):
|
||||
|
@ -64,6 +66,90 @@ class TestAAQPage(TestUtilities):
|
|||
self.sumo_pages.aaq_form_page.get_learn_more_button_locator()
|
||||
).to_be_hidden()
|
||||
|
||||
# C1511570
|
||||
@pytest.mark.aaqPage
|
||||
@pytest.mark.parametrize("username", ['', 'TEST_ACCOUNT_12', 'TEST_ACCOUNT_MODERATOR'])
|
||||
def test_scam_banner_premium_products_not_displayed(self, username):
|
||||
if username != '':
|
||||
self.logger.info("Signing in with a user account")
|
||||
self.start_existing_session(super().username_extraction_from_email(
|
||||
self.user_secrets_accounts[username]
|
||||
))
|
||||
self.logger.info("Navigating to each premium product solutions page")
|
||||
for premium_product in super().general_test_data["premium_products"]:
|
||||
self.navigate_to_link(
|
||||
super().general_test_data["product_solutions"][premium_product]
|
||||
)
|
||||
|
||||
self.logger.info("Verifying that the scam banner is not displayed")
|
||||
expect(
|
||||
self.sumo_pages.product_solutions_page.get_scam_banner_locator()
|
||||
).to_be_hidden()
|
||||
|
||||
if username != '':
|
||||
self.logger.info("Clicking on the ask now button")
|
||||
self.sumo_pages.product_solutions_page._click_ask_now_button()
|
||||
self.wait_for_url_to_be(
|
||||
super().aaq_question_test_data["products_aaq_url"][premium_product]
|
||||
)
|
||||
|
||||
self.logger.info("Verifying that the scam banner is not displayed")
|
||||
expect(
|
||||
self.sumo_pages.product_solutions_page.get_scam_banner_locator()
|
||||
).to_be_hidden()
|
||||
|
||||
# C2190040
|
||||
@pytest.mark.aaqPage
|
||||
@pytest.mark.parametrize("username", ['', 'TEST_ACCOUNT_12', 'TEST_ACCOUNT_MODERATOR'])
|
||||
def test_scam_banner_for_freemium_products_is_displayed(self, username):
|
||||
if username != '':
|
||||
self.logger.info("Signing in with a user account")
|
||||
self.start_existing_session(super().username_extraction_from_email(
|
||||
self.user_secrets_accounts[username]
|
||||
))
|
||||
|
||||
self.logger.info("Navigating to each freemium product solutions page")
|
||||
for freemium_product in super().general_test_data["freemium_products"]:
|
||||
self.navigate_to_link(
|
||||
super().general_test_data["product_solutions"][freemium_product]
|
||||
)
|
||||
|
||||
self.logger.info("Clicking on the 'Learn More' button")
|
||||
self.sumo_pages.product_solutions_page._click_on_scam_alert_banner_learn_more()
|
||||
|
||||
self.logger.info("Verifying that the correct kb article is displayed")
|
||||
check.equal(
|
||||
self.sumo_pages.kb_article_page.get_text_of_article_title(),
|
||||
ProductSolutionsMessages.AVOID_TECH_SUPPORT_SCAMS_ARTICLE_TITLE,
|
||||
f"Incorrect KB article title. "
|
||||
f"Expected: {ProductSolutionsMessages.AVOID_TECH_SUPPORT_SCAMS_ARTICLE_TITLE} "
|
||||
f"Received: {self.sumo_pages.kb_article_page.get_text_of_article_title()}"
|
||||
)
|
||||
if username != '':
|
||||
self.logger.info("Navigating back to the product solutions page")
|
||||
self.navigate_back()
|
||||
self.wait_for_url_to_be(
|
||||
super().general_test_data["product_solutions"][freemium_product]
|
||||
)
|
||||
|
||||
self.logger.info("Clicking on the ask now button")
|
||||
self.sumo_pages.product_solutions_page._click_ask_now_button()
|
||||
self.wait_for_url_to_be(
|
||||
super().aaq_question_test_data["products_aaq_url"][freemium_product]
|
||||
)
|
||||
|
||||
self.logger.info("Clicking on the 'Learn More' button")
|
||||
self.sumo_pages.product_solutions_page._click_on_scam_alert_banner_learn_more()
|
||||
|
||||
self.logger.info("Verifying that the correct kb article is displayed")
|
||||
check.equal(
|
||||
self.sumo_pages.kb_article_page.get_text_of_article_title(),
|
||||
ProductSolutionsMessages.AVOID_TECH_SUPPORT_SCAMS_ARTICLE_TITLE,
|
||||
f"Incorrect KB article title. "
|
||||
f"Expected: {ProductSolutionsMessages.AVOID_TECH_SUPPORT_SCAMS_ARTICLE_TITLE} "
|
||||
f"Received: {self.sumo_pages.kb_article_page.get_text_of_article_title()}"
|
||||
)
|
||||
|
||||
# C890537
|
||||
@pytest.mark.aaqPage
|
||||
def test_corresponding_aaq_product_name_and_image_are_displayed(self):
|
||||
|
@ -145,7 +231,7 @@ class TestAAQPage(TestUtilities):
|
|||
# C890612
|
||||
@pytest.mark.aaqPage
|
||||
def test_aaq_form_cancel_button_freemium_products(self):
|
||||
self.logger.info("Signing in with a normal user account")
|
||||
self.logger.info("Signing in with a admin user account")
|
||||
self.start_existing_session(super().username_extraction_from_email(
|
||||
self.user_secrets_accounts["TEST_ACCOUNT_MODERATOR"]
|
||||
))
|
||||
|
@ -198,7 +284,7 @@ class TestAAQPage(TestUtilities):
|
|||
# C890614, C890613, C890538
|
||||
@pytest.mark.aaqPage
|
||||
def test_post_aaq_questions_for_all_freemium_products_topics(self):
|
||||
self.logger.info("Signing in with a normal user account")
|
||||
self.logger.info("Signing in with a admin user account")
|
||||
self.start_existing_session(super().username_extraction_from_email(
|
||||
self.user_secrets_accounts["TEST_ACCOUNT_MODERATOR"]
|
||||
))
|
||||
|
@ -266,7 +352,7 @@ class TestAAQPage(TestUtilities):
|
|||
|
||||
@pytest.mark.aaqPage
|
||||
def test_share_firefox_data_functionality(self):
|
||||
self.logger.info("Signing in with a normal user account")
|
||||
self.logger.info("Signing in with a admin user account")
|
||||
self.start_existing_session(super().username_extraction_from_email(
|
||||
self.user_secrets_accounts["TEST_ACCOUNT_MODERATOR"]
|
||||
))
|
||||
|
@ -327,7 +413,7 @@ class TestAAQPage(TestUtilities):
|
|||
|
||||
@pytest.mark.aaqPage
|
||||
def test_additional_system_details_user_agent_information(self):
|
||||
self.logger.info("Signing in with a normal user account")
|
||||
self.logger.info("Signing in with a admin user account")
|
||||
self.start_existing_session(super().username_extraction_from_email(
|
||||
self.user_secrets_accounts["TEST_ACCOUNT_MODERATOR"]
|
||||
))
|
||||
|
@ -371,7 +457,7 @@ class TestAAQPage(TestUtilities):
|
|||
"Firefox " + super().aaq_question_test_data["troubleshoot_product_and_os_versions"][1]
|
||||
]
|
||||
|
||||
self.logger.info("Signing in with a normal user account")
|
||||
self.logger.info("Signing in with a admin user account")
|
||||
self.start_existing_session(super().username_extraction_from_email(
|
||||
self.user_secrets_accounts["TEST_ACCOUNT_MODERATOR"]
|
||||
))
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -236,7 +236,6 @@ class TestContributeArticlePage(TestUtilities):
|
|||
)
|
||||
|
||||
# Need to add tests for "How you can contribute" section
|
||||
|
||||
# C2165418
|
||||
@pytest.mark.contributePagesTests
|
||||
def test_contribute_article_other_ways_to_contribute_redirect_to_the_correct_page(self):
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import pytest
|
||||
import pytest_check as check
|
||||
|
||||
from playwright.sync_api import TimeoutError, expect
|
||||
from playwright.sync_api import TimeoutError, expect, Error
|
||||
from playwright_tests.core.testutilities import TestUtilities
|
||||
from playwright_tests.messages.AAQ_messages.aaq_widget import AAQWidgetMessages
|
||||
from playwright_tests.messages.contribute_pages_messages.con_page_messages import (
|
||||
|
@ -29,7 +29,7 @@ class TestPopularTopicsPage(TestUtilities):
|
|||
self.sumo_pages.product_topics_page._click_on_a_navbar_option(option)
|
||||
try:
|
||||
self.wait_for_url_to_be(option_url)
|
||||
except TimeoutError:
|
||||
except (TimeoutError, Error):
|
||||
self.logger.info("Failed click, retrying")
|
||||
self.sumo_pages.product_topics_page._click_on_a_navbar_option(option)
|
||||
self.wait_for_url_to_be(option_url)
|
||||
|
|
|
@ -250,7 +250,7 @@ class TestEditMyProfile(TestUtilities):
|
|||
fxa_page = tab.value
|
||||
print("Tab open")
|
||||
|
||||
assert fxa_page.url in FxAPageMessages.ACCOUNT_SETTINGS_URL
|
||||
assert FxAPageMessages.ACCOUNT_SETTINGS_URL in fxa_page.url
|
||||
|
||||
# C1491461
|
||||
@pytest.mark.editUserProfileTests
|
||||
|
|
Загрузка…
Ссылка в новой задаче