diff --git a/.github/workflows/playwright.yml b/.github/workflows/playwright.yml index bdb288738..b59ae6ff7 100644 --- a/.github/workflows/playwright.yml +++ b/.github/workflows/playwright.yml @@ -1,25 +1,27 @@ 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' + +env: + TEST_ACCOUNT_12: ${{secrets.AUTOMATION_TEST_ACCOUNT_12}} + TEST_ACCOUNT_13: ${{secrets.AUTOMATION_TEST_ACCOUNT_13}} + TEST_ACCOUNT_MESSAGE_1: ${{secrets.AUTOMATION_TEST_ACCOUNT_MESSAGE_1}} + TEST_ACCOUNT_MESSAGE_2: ${{secrets.AUTOMATION_TEST_ACCOUNT_MESSAGE_2}} + TEST_ACCOUNT_MESSAGE_3: ${{secrets.AUTOMATION_TEST_ACCOUNT_MESSAGE_3}} + TEST_ACCOUNT_MESSAGE_4: ${{secrets.AUTOMATION_TEST_ACCOUNT_MESSAGE_4}} + TEST_ACCOUNT_MESSAGE_5: ${{secrets.AUTOMATION_TEST_ACCOUNT_MESSAGE_5}} + TEST_ACCOUNT_MESSAGE_6: ${{secrets.AUTOMATION_TEST_ACCOUNT_MESSAGE_6}} + 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: - name: 'Playwright Tests' + playwright_tests: runs-on: ubuntu-latest - env: - TEST_ACCOUNT_12: ${{secrets.AUTOMATION_TEST_ACCOUNT_12}} - TEST_ACCOUNT_13: ${{secrets.AUTOMATION_TEST_ACCOUNT_13}} - TEST_ACCOUNT_MESSAGE_1: ${{secrets.AUTOMATION_TEST_ACCOUNT_MESSAGE_1}} - TEST_ACCOUNT_MESSAGE_2: ${{secrets.AUTOMATION_TEST_ACCOUNT_MESSAGE_2}} - TEST_ACCOUNT_MESSAGE_3: ${{secrets.AUTOMATION_TEST_ACCOUNT_MESSAGE_3}} - TEST_ACCOUNT_MESSAGE_4: ${{secrets.AUTOMATION_TEST_ACCOUNT_MESSAGE_4}} - TEST_ACCOUNT_MESSAGE_5: ${{secrets.AUTOMATION_TEST_ACCOUNT_MESSAGE_5}} - TEST_ACCOUNT_MESSAGE_6: ${{secrets.AUTOMATION_TEST_ACCOUNT_MESSAGE_6}} - TEST_ACCOUNT_SPECIAL_CHARS: ${{secrets.AUTOMATION_TEST_ACCOUNT_SPECIAL_CHARS}} - TEST_ACCOUNTS_PS: ${{secrets.AUTOMATION_ACCOUNTS_PASSWORD}} - TEST_ACCOUNT_MODERATOR: ${{secrets.AUTOMATION_MODERATOR_ACCOUNT}} - 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 diff --git a/playwright_tests/core/basepage.py b/playwright_tests/core/basepage.py index cf84996e8..0e0a92029 100644 --- a/playwright_tests/core/basepage.py +++ b/playwright_tests/core/basepage.py @@ -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) diff --git a/playwright_tests/core/testutilities.py b/playwright_tests/core/testutilities.py index 94a3930ee..618930b5a 100644 --- a/playwright_tests/core/testutilities.py +++ b/playwright_tests/core/testutilities.py @@ -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, "") diff --git a/playwright_tests/flows/aaq_flows/aaq_flow.py b/playwright_tests/flows/aaq_flows/aaq_flow.py index 9ffe411ba..dcd5f285f 100644 --- a/playwright_tests/flows/aaq_flows/aaq_flow.py +++ b/playwright_tests/flows/aaq_flows/aaq_flow.py @@ -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"] diff --git a/playwright_tests/flows/article_flows/add_kb_article_flow.py b/playwright_tests/flows/article_flows/add_kb_article_flow.py index a1e9c5969..0bc5bd34e 100644 --- a/playwright_tests/flows/article_flows/add_kb_article_flow.py +++ b/playwright_tests/flows/article_flows/add_kb_article_flow.py @@ -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) diff --git a/playwright_tests/flows/auth_flows/auth_flow.py b/playwright_tests/flows/auth_flows/auth_flow.py index c3eff3a13..d1b84cc08 100644 --- a/playwright_tests/flows/auth_flows/auth_flow.py +++ b/playwright_tests/flows/auth_flows/auth_flow.py @@ -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: diff --git a/playwright_tests/flows/messaging_system_flows/messaging_system_flow.py b/playwright_tests/flows/messaging_system_flows/messaging_system_flow.py index eb0ef0f5f..56f40f42e 100644 --- a/playwright_tests/flows/messaging_system_flows/messaging_system_flow.py +++ b/playwright_tests/flows/messaging_system_flows/messaging_system_flow.py @@ -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) diff --git a/playwright_tests/flows/user_profile_flows/edit_profile_data_flow.py b/playwright_tests/flows/user_profile_flows/edit_profile_data_flow.py index 05a347bda..c467cdf5c 100644 --- a/playwright_tests/flows/user_profile_flows/edit_profile_data_flow.py +++ b/playwright_tests/flows/user_profile_flows/edit_profile_data_flow.py @@ -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() diff --git a/playwright_tests/messages/AAQ_messages/edit_question_page_messages.py b/playwright_tests/messages/AAQ_messages/edit_question_page_messages.py new file mode 100644 index 000000000..bf3fa07d3 --- /dev/null +++ b/playwright_tests/messages/AAQ_messages/edit_question_page_messages.py @@ -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" diff --git a/playwright_tests/messages/auth_pages_messages/fxa_page_messages.py b/playwright_tests/messages/auth_pages_messages/fxa_page_messages.py index 8125e27c1..b9db18635 100644 --- a/playwright_tests/messages/auth_pages_messages/fxa_page_messages.py +++ b/playwright_tests/messages/auth_pages_messages/fxa_page_messages.py @@ -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" diff --git a/playwright_tests/messages/product_solutions_page_messages/product_solutions_messages.py b/playwright_tests/messages/product_solutions_page_messages/product_solutions_messages.py index 9aeef599d..f4516bd82 100644 --- a/playwright_tests/messages/product_solutions_page_messages/product_solutions_messages.py +++ b/playwright_tests/messages/product_solutions_page_messages/product_solutions_messages.py @@ -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" diff --git a/playwright_tests/pages/aaq_pages/aaq_form_page.py b/playwright_tests/pages/aaq_pages/aaq_form_page.py index 8289068bc..9108d082f 100644 --- a/playwright_tests/pages/aaq_pages/aaq_form_page.py +++ b/playwright_tests/pages/aaq_pages/aaq_form_page.py @@ -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) diff --git a/playwright_tests/pages/articles/kb_article_page.py b/playwright_tests/pages/articles/kb_article_page.py index 519746f98..fe1091efc 100644 --- a/playwright_tests/pages/articles/kb_article_page.py +++ b/playwright_tests/pages/articles/kb_article_page.py @@ -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) diff --git a/playwright_tests/pages/articles/kb_article_show_history_page.py b/playwright_tests/pages/articles/kb_article_show_history_page.py index d1fd94a41..3d498a308 100644 --- a/playwright_tests/pages/articles/kb_article_show_history_page.py +++ b/playwright_tests/pages/articles/kb_article_show_history_page.py @@ -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) diff --git a/playwright_tests/pages/articles/submit_kb_article_page.py b/playwright_tests/pages/articles/submit_kb_article_page.py index b55aedb05..f4fbb8950 100644 --- a/playwright_tests/pages/articles/submit_kb_article_page.py +++ b/playwright_tests/pages/articles/submit_kb_article_page.py @@ -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) diff --git a/playwright_tests/pages/contact_support_pages/contact_support_page.py b/playwright_tests/pages/contact_support_pages/contact_support_page.py index 4dc7f29fe..7d4a578b8 100644 --- a/playwright_tests/pages/contact_support_pages/contact_support_page.py +++ b/playwright_tests/pages/contact_support_pages/contact_support_page.py @@ -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) diff --git a/playwright_tests/pages/forums_pages/product_support_forum.py b/playwright_tests/pages/forums_pages/product_support_forum.py new file mode 100644 index 000000000..9677c6d29 --- /dev/null +++ b/playwright_tests/pages/forums_pages/product_support_forum.py @@ -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 diff --git a/playwright_tests/pages/forums_pages/support_forums_page.py b/playwright_tests/pages/forums_pages/support_forums_page.py index beba82052..f6e0e542c 100644 --- a/playwright_tests/pages/forums_pages/support_forums_page.py +++ b/playwright_tests/pages/forums_pages/support_forums_page.py @@ -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) diff --git a/playwright_tests/pages/product_solutions_pages/product_solutions_page.py b/playwright_tests/pages/product_solutions_pages/product_solutions_page.py index fdfec8b6d..432c1c381 100644 --- a/playwright_tests/pages/product_solutions_pages/product_solutions_page.py +++ b/playwright_tests/pages/product_solutions_pages/product_solutions_page.py @@ -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) diff --git a/playwright_tests/pages/product_topics_pages/product_topics_page.py b/playwright_tests/pages/product_topics_pages/product_topics_page.py index a26acafcc..9473366d4 100644 --- a/playwright_tests/pages/product_topics_pages/product_topics_page.py +++ b/playwright_tests/pages/product_topics_pages/product_topics_page.py @@ -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) diff --git a/playwright_tests/pages/sumo_pages.py b/playwright_tests/pages/sumo_pages.py index d05dfd357..eac7a4bd8 100644 --- a/playwright_tests/pages/sumo_pages.py +++ b/playwright_tests/pages/sumo_pages.py @@ -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) diff --git a/playwright_tests/pages/user_questions_pages/questions_page.py b/playwright_tests/pages/user_questions_pages/questions_page.py index 76cac27ab..d562a5e97 100644 --- a/playwright_tests/pages/user_questions_pages/questions_page.py +++ b/playwright_tests/pages/user_questions_pages/questions_page.py @@ -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) diff --git a/playwright_tests/pytest.ini b/playwright_tests/pytest.ini index 7d6113047..548ecd3ae 100644 --- a/playwright_tests/pytest.ini +++ b/playwright_tests/pytest.ini @@ -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. diff --git a/playwright_tests/test_data/aaq_question.json b/playwright_tests/test_data/aaq_question.json index 9256fab37..8b895d4d2 100644 --- a/playwright_tests/test_data/aaq_question.json +++ b/playwright_tests/test_data/aaq_question.json @@ -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", diff --git a/playwright_tests/tests/aaq_tests/test_aaq_page.py b/playwright_tests/tests/aaq_tests/test_aaq_form_page.py similarity index 81% rename from playwright_tests/tests/aaq_tests/test_aaq_page.py rename to playwright_tests/tests/aaq_tests/test_aaq_form_page.py index 8660ea98e..6e4bbf54e 100644 --- a/playwright_tests/tests/aaq_tests/test_aaq_page.py +++ b/playwright_tests/tests/aaq_tests/test_aaq_form_page.py @@ -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"] )) diff --git a/playwright_tests/tests/aaq_tests/test_posted_questions.py b/playwright_tests/tests/aaq_tests/test_posted_questions.py new file mode 100644 index 000000000..3b97c9628 --- /dev/null +++ b/playwright_tests/tests/aaq_tests/test_posted_questions.py @@ -0,0 +1,1286 @@ +import os + +import pytest +import pytest_check as check +from playwright_tests.core.testutilities import TestUtilities +from playwright.sync_api import expect + +from playwright_tests.messages.AAQ_messages.edit_question_page_messages import ( + EditQuestionPageMessages) +from playwright_tests.messages.auth_pages_messages.fxa_page_messages import ( + FxAPageMessages) +from playwright_tests.messages.contact_support_page_messages.contact_support_messages import ( + ContactSupportMessages) + + +class TestPostedQuestions(TestUtilities): + + # C2191086, C2191094, C2191263, C2191263 + @pytest.mark.postedQuestions + def test_posted_question_details_for_admin_users(self): + self.logger.info("Signing in with a non admin user account") + self.start_existing_session(super().username_extraction_from_email( + self.user_secrets_accounts["TEST_ACCOUNT_12"] + )) + + self.logger.info("Posting a Firefox product question") + self.navigate_to_link(super().aaq_question_test_data["products_aaq_url"]["Firefox"]) + + question_info = self.sumo_pages.aaq_flow.submit_an_aaq_question_for_a_product( + subject=super().aaq_question_test_data["valid_firefox_question"]["subject"], + topic_name=self.sumo_pages.aaq_form_page.get_aaq_form_topic_options()[0], + body=super().aaq_question_test_data["valid_firefox_question"]["question_body"], + attach_image=False + ) + + self.logger.info("Deleting session cookies and signing in with an admin account") + super().delete_cookies() + + self.start_existing_session(super().username_extraction_from_email( + self.user_secrets_accounts["TEST_ACCOUNT_MODERATOR"] + )) + + self.navigate_to_link(question_info['question_page_url']) + + self.logger.info("Navigating to the posted question") + + self.logger.info("Verifying that the scam banner is not displayed") + expect( + self.sumo_pages.product_solutions_page.get_scam_banner_locator() + ).to_be_visible() + + self.logger.info("Verifying that the still need help banner is not displayed") + expect( + self.sumo_pages.product_solutions_page.get_still_need_help_locator() + ).to_be_hidden() + + self.logger.info("Deleting the posted question") + self.sumo_pages.question_page.click_delete_this_question_question_tools_option() + self.sumo_pages.question_page.click_delete_this_question_button() + + # C2191092, C2191263 + @pytest.mark.postedQuestions + def test_edit_this_question_functionality_not_signed_in(self): + self.logger.info("Signing in with an admin account") + + self.start_existing_session(super().username_extraction_from_email( + self.user_secrets_accounts["TEST_ACCOUNT_MODERATOR"] + )) + + self.logger.info("Posting a Firefox product question") + self.navigate_to_link(super().aaq_question_test_data["products_aaq_url"]["Firefox"]) + + self.sumo_pages.aaq_flow.submit_an_aaq_question_for_a_product( + subject=super().aaq_question_test_data["valid_firefox_question"]["subject"], + topic_name=self.sumo_pages.aaq_form_page.get_aaq_form_topic_options()[0], + body=super().aaq_question_test_data["valid_firefox_question"]["simple_body_text"], + attach_image=False + ) + + self.logger.info("Deleting session cookies") + self.delete_cookies() + + self.logger.info("Verifying that the 'edit this question' nav option is not available") + + expect( + self.sumo_pages.question_page.get_edit_this_question_option_locator() + ).to_be_hidden() + + self.logger.info("Navigating to the edit endpoint") + self.navigate_to_link( + self.get_page_url() + EditQuestionPageMessages.EDIT_QUESTION_URL_ENDPOINT + ) + + self.logger.info("Verifying that the user is to the auth page") + assert ( + FxAPageMessages.AUTH_PAGE_URL in self.get_page_url() + ) + + self.logger.info("Navigating back to the question") + self.navigate_back() + + self.logger.info("Signing in with an admin account") + self.start_existing_session(super().username_extraction_from_email( + self.user_secrets_accounts["TEST_ACCOUNT_MODERATOR"] + )) + + self.logger.info("Deleting the posted question") + self.sumo_pages.question_page.click_delete_this_question_question_tools_option() + self.sumo_pages.question_page.click_delete_this_question_button() + + # C2191262, C2436105, C2191263 + # To add image tests + @pytest.mark.postedQuestions + @pytest.mark.parametrize("username", ['TEST_ACCOUNT_12', 'TEST_ACCOUNT_MODERATOR']) + def test_cancel_edit_this_question_functionality(self, username): + self.logger.info("Signing in with a non admin user account") + self.start_existing_session(super().username_extraction_from_email( + self.user_secrets_accounts["TEST_ACCOUNT_12"] + )) + + self.logger.info("Posting a Firefox product question") + self.navigate_to_link(super().aaq_question_test_data["products_aaq_url"]["Firefox"]) + + question_info = self.sumo_pages.aaq_flow.submit_an_aaq_question_for_a_product( + subject=super().aaq_question_test_data["valid_firefox_question"]["subject"], + topic_name=self.sumo_pages.aaq_form_page.get_aaq_form_topic_options()[0], + body=super().aaq_question_test_data["valid_firefox_question"]["simple_body_text"], + attach_image=False + ) + + if username == 'TEST_ACCOUNT_MODERATOR': + self.logger.info("Deleting session cookies and signing in with an admin account") + super().delete_cookies() + + self.start_existing_session(super().username_extraction_from_email( + self.user_secrets_accounts["TEST_ACCOUNT_MODERATOR"] + )) + + self.navigate_to_link(question_info['question_page_url']) + self.logger.info("Clicking on the 'Edit this question' option") + self.sumo_pages.question_page.click_on_edit_this_question_question_tools_option() + + self.logger.info("Verifying that the subject field contains the correct value") + check.equal( + self.sumo_pages.aaq_form_page.get_value_of_subject_input_field(), + question_info['aaq_subject'], + f"Incorrect question subject displayed. " + f"Expected: {question_info['aaq_subject']} " + f"Received: {self.sumo_pages.aaq_form_page.get_value_of_subject_input_field()}" + ) + + self.logger.info("Verifying that the question body contains the correct value") + check.equal( + self.sumo_pages.aaq_form_page.get_value_of_question_body_textarea_field(), + question_info['question_body'] + + ) + + self.logger.info("Adding text inside the Subject field") + self.sumo_pages.aaq_form_page.clear_subject_input_field() + self.sumo_pages.aaq_form_page.add_text_to_aaq_form_subject_field( + super().aaq_question_test_data['valid_firefox_question']['subject_updated'] + ) + + self.logger.info("Adding text inside the body field") + self.sumo_pages.aaq_form_page.clear_the_question_body_textarea_field() + self.sumo_pages.aaq_form_page.add_text_to_aaq_textarea_field( + super().aaq_question_test_data['valid_firefox_question']['body_updated'] + ) + + self.logger.info("Adding information inside the troubleshoot information textarea") + self.sumo_pages.aaq_form_page.add_text_to_troubleshooting_information_textarea( + super().aaq_question_test_data['troubleshooting_information_textarea_field'] + ) + + self.logger.info("Clicking on the 'Cancel' button") + self.sumo_pages.aaq_form_page.click_aaq_form_cancel_button() + + self.logger.info("Verifying that the 'Modified' text is not displayed") + expect( + self.sumo_pages.question_page.get_modified_question_locator() + ).to_be_hidden() + + self.logger.info("Verifying that the subject and body fields are the same") + check.equal( + self.sumo_pages.question_page.get_question_header(), + question_info['aaq_subject'] + ) + + check.equal( + self.sumo_pages.question_page.get_question_body(), + question_info['question_body'] + '\n' + ) + + if username == 'TEST_ACCOUNT_12': + self.logger.info("Verifying that the additional question details option is hidden") + expect( + self.sumo_pages.question_page.get_question_details_button_locator() + ).to_be_hidden() + elif username == "TEST_ACCOUNT_MODERATOR": + self.logger.info("Clicking on the 'Question Details' option") + self.sumo_pages.question_page.click_on_question_details_button() + + self.logger.info("Clicking on the 'More system details' option") + self.sumo_pages.question_page.click_on_more_system_details_option() + + self.logger.info("Verifying that the more information section is not displayed") + expect( + self.sumo_pages.question_page.get_more_information_locator() + ).to_be_hidden() + + self.logger.info("Closing the more information panel") + self.sumo_pages.question_page.click_on_the_additional_system_panel_close_button() + + if username != 'TEST_ACCOUNT_MODERATOR': + self.logger.info("Deleting session cookies and signing in with an admin account") + super().delete_cookies() + + self.start_existing_session(super().username_extraction_from_email( + self.user_secrets_accounts["TEST_ACCOUNT_MODERATOR"] + )) + + self.logger.info("Deleting the posted question") + self.sumo_pages.question_page.click_delete_this_question_question_tools_option() + self.sumo_pages.question_page.click_delete_this_question_button() + + # C2191263 + @pytest.mark.postedQuestions + def test_edit_other_user_question_non_admin(self): + self.logger.info("Signing in with a non admin user account") + self.start_existing_session(super().username_extraction_from_email( + self.user_secrets_accounts["TEST_ACCOUNT_13"] + )) + + self.logger.info("Posting a Firefox product question") + self.navigate_to_link(super().aaq_question_test_data["products_aaq_url"]["Firefox"]) + + question_info = self.sumo_pages.aaq_flow.submit_an_aaq_question_for_a_product( + subject=super().aaq_question_test_data["valid_firefox_question"]["subject"], + topic_name=self.sumo_pages.aaq_form_page.get_aaq_form_topic_options()[0], + body=super().aaq_question_test_data["valid_firefox_question"]["simple_body_text"], + attach_image=False + ) + + self.logger.info("Deleting session cookies") + self.delete_cookies() + + self.logger.info("Signing in with a non admin user account") + self.start_existing_session(super().username_extraction_from_email( + self.user_secrets_accounts["TEST_ACCOUNT_12"] + )) + + self.logger.info("Verifying that the 'Edit this question' option is not available") + expect( + self.sumo_pages.question_page.get_edit_this_question_option_locator() + ).to_be_hidden() + + self.logger.info("Manually navigating to the '/edit' endpoint and verifying that 403 is " + "returned") + + with self.page.expect_navigation() as navigation_info: + self.navigate_to_link(question_info['question_page_url'] + EditQuestionPageMessages. + EDIT_QUESTION_URL_ENDPOINT) + response = navigation_info.value + check.equal( + response.status, + 403 + ) + + self.logger.info("Navigating back to the posted question") + self.navigate_back() + + self.logger.info("Signing in with an admin account") + self.start_existing_session(super().username_extraction_from_email( + self.user_secrets_accounts["TEST_ACCOUNT_MODERATOR"] + )) + + self.logger.info("Deleting the posted question") + self.sumo_pages.question_page.click_delete_this_question_question_tools_option() + self.sumo_pages.question_page.click_delete_this_question_button() + + # C2191262, C2436105, C2191263 + # To add image tests + @pytest.mark.postedQuestions + @pytest.mark.parametrize("username", ['TEST_ACCOUNT_12', 'TEST_ACCOUNT_MODERATOR']) + def test_edit_this_question_functionality(self, username): + self.logger.info("Signing in with a non admin user account") + user = super().username_extraction_from_email( + self.user_secrets_accounts[username] + ) + self.start_existing_session(super().username_extraction_from_email( + self.user_secrets_accounts["TEST_ACCOUNT_12"] + )) + + self.logger.info("Posting a Firefox product question") + self.navigate_to_link(super().aaq_question_test_data["products_aaq_url"]["Firefox"]) + + question_info = self.sumo_pages.aaq_flow.submit_an_aaq_question_for_a_product( + subject=super().aaq_question_test_data["valid_firefox_question"]["subject"], + topic_name=self.sumo_pages.aaq_form_page.get_aaq_form_topic_options()[0], + body=super().aaq_question_test_data["valid_firefox_question"]["simple_body_text"], + attach_image=False + ) + + if username == 'TEST_ACCOUNT_MODERATOR': + self.logger.info("Deleting session cookies and signing in with an admin account") + super().delete_cookies() + + self.start_existing_session(super().username_extraction_from_email( + self.user_secrets_accounts["TEST_ACCOUNT_MODERATOR"] + )) + + self.navigate_to_link(question_info['question_page_url']) + self.logger.info("Clicking on the 'Edit this question' option") + self.sumo_pages.question_page.click_on_edit_this_question_question_tools_option() + + self.logger.info("Verifying that the subject field contains the correct value") + check.equal( + self.sumo_pages.aaq_form_page.get_value_of_subject_input_field(), + question_info['aaq_subject'], + f"Incorrect question subject displayed. " + f"Expected: {question_info['aaq_subject']} " + f"Received: {self.sumo_pages.aaq_form_page.get_value_of_subject_input_field()}" + ) + + self.logger.info("Verifying that the question body contains the correct value") + check.equal( + self.sumo_pages.aaq_form_page.get_value_of_question_body_textarea_field(), + question_info['question_body'] + + ) + + self.logger.info("Adding text inside the Subject field") + self.sumo_pages.aaq_form_page.clear_subject_input_field() + self.sumo_pages.aaq_form_page.add_text_to_aaq_form_subject_field( + super().aaq_question_test_data['valid_firefox_question']['subject_updated'] + ) + + self.logger.info("Adding text inside the body field") + self.sumo_pages.aaq_form_page.clear_the_question_body_textarea_field() + self.sumo_pages.aaq_form_page.add_text_to_aaq_textarea_field( + super().aaq_question_test_data['valid_firefox_question']['body_updated'] + ) + + self.logger.info("Adding information inside the troubleshoot information textarea") + self.sumo_pages.aaq_form_page.add_text_to_troubleshooting_information_textarea( + super().aaq_question_test_data['troubleshooting_information_textarea_field'] + ) + + self.logger.info("Clicking on the 'Submit' button") + self.sumo_pages.aaq_form_page.click_aaq_edit_submit_button() + + self.logger.info("Verifying that the 'Modified' text is displayed") + expect( + self.sumo_pages.question_page.get_modified_question_locator() + ).to_be_visible() + + self.logger.info("Verifying that the username is displayed inside the modified by text") + check.is_in( + user, + self.sumo_pages.question_page.get_modified_by_text() + ) + + self.logger.info("Verifying that the subject and body are modified") + check.equal( + self.sumo_pages.question_page.get_question_header(), + super().aaq_question_test_data['valid_firefox_question']['subject_updated'] + ) + + check.equal( + self.sumo_pages.question_page.get_question_body(), + super().aaq_question_test_data['valid_firefox_question']['body_updated'] + '\n' + ) + + if username == 'TEST_ACCOUNT_12': + self.logger.info("Verifying that the additional question details option is hidden") + expect( + self.sumo_pages.question_page.get_question_details_button_locator() + ).to_be_hidden() + elif username == "TEST_ACCOUNT_MODERATOR": + self.logger.info("Clicking on the 'Question Details' option") + self.sumo_pages.question_page.click_on_question_details_button() + + self.logger.info("Clicking on the 'More system details' option") + self.sumo_pages.question_page.click_on_more_system_details_option() + + self.logger.info("Verifying that the more information section displays the update") + expect( + self.sumo_pages.question_page.get_more_information_with_text_locator( + super().aaq_question_test_data['troubleshooting_information_textarea_field'] + ) + ).to_be_visible() + + self.logger.info("Closing the more information panel") + self.sumo_pages.question_page.click_on_the_additional_system_panel_close_button() + + if username != 'TEST_ACCOUNT_MODERATOR': + self.logger.info("Deleting session cookies and signing in with an admin account") + super().delete_cookies() + + self.start_existing_session(super().username_extraction_from_email( + self.user_secrets_accounts["TEST_ACCOUNT_MODERATOR"] + )) + + self.logger.info("Deleting the posted question") + self.sumo_pages.question_page.click_delete_this_question_question_tools_option() + self.sumo_pages.question_page.click_delete_this_question_button() + + # C2191263 + @pytest.mark.postedQuestions + def test_delete_question_cancel_button(self): + self.logger.info("Signing in with a non admin user account") + self.start_existing_session(super().username_extraction_from_email( + self.user_secrets_accounts["TEST_ACCOUNT_13"] + )) + + self.logger.info("Posting a Firefox product question") + self.navigate_to_link(super().aaq_question_test_data["products_aaq_url"]["Firefox"]) + + question_info_one = self.sumo_pages.aaq_flow.submit_an_aaq_question_for_a_product( + subject=super().aaq_question_test_data["valid_firefox_question"]["subject"], + topic_name=self.sumo_pages.aaq_form_page.get_aaq_form_topic_options()[0], + body=super().aaq_question_test_data["valid_firefox_question"]["simple_body_text"], + attach_image=False + ) + + self.logger.info("Deleting user session") + self.delete_cookies() + + self.logger.info("Signing in with a different non admin user account") + self.start_existing_session(super().username_extraction_from_email( + self.user_secrets_accounts["TEST_ACCOUNT_12"] + )) + + self.logger.info("Posting a Firefox product question") + self.navigate_to_link(super().aaq_question_test_data["products_aaq_url"]["Firefox"]) + + question_info_two = self.sumo_pages.aaq_flow.submit_an_aaq_question_for_a_product( + subject=super().aaq_question_test_data["valid_firefox_question"]["subject"], + topic_name=self.sumo_pages.aaq_form_page.get_aaq_form_topic_options()[0], + body=super().aaq_question_test_data["valid_firefox_question"]["simple_body_text"], + attach_image=False + ) + + self.navigate_to_link( + question_info_one['question_page_url'] + ) + + self.logger.info("Verifying that the 'Delete this question' option is not available") + expect( + self.sumo_pages.question_page.get_delete_this_question_locator() + ).to_be_hidden() + + self.logger.info("Manually navigating to the delete endpoint and verifying that 403 is " + "returned") + + with self.page.expect_navigation() as navigation_info: + self.navigate_to_link( + question_info_one['question_page_url'] + EditQuestionPageMessages. + DELETE_QUESTION_URL_ENDPOINT) + response = navigation_info.value + check.equal( + response.status, + 403 + ) + + self.navigate_to_link( + question_info_two['question_page_url'] + ) + + self.logger.info("Verifying that the 'Delete this question' option is not available") + expect( + self.sumo_pages.question_page.get_delete_this_question_locator() + ).to_be_hidden() + + self.logger.info("Manually navigating to the delete endpoint and verifying that 403 is " + "returned") + + with self.page.expect_navigation() as navigation_info: + self.navigate_to_link( + question_info_one['question_page_url'] + EditQuestionPageMessages. + DELETE_QUESTION_URL_ENDPOINT) + response = navigation_info.value + check.equal( + response.status, + 403 + ) + + self.logger.info("Navigating back to the question page and deleting session cookies") + self.navigate_back() + self.delete_cookies() + + 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"] + )) + + self.logger.info("Clicking on the 'Delete this question option'") + self.sumo_pages.question_page.click_delete_this_question_question_tools_option() + + self.logger.info("Clicking on the 'Cancel' button and verifying that we are on the " + "question page") + + self.sumo_pages.aaq_form_page.click_aaq_form_cancel_button() + + expect( + self.page + ).to_have_url(question_info_two['question_page_url']) + + self.logger.info("Deleting the posted question") + self.sumo_pages.question_page.click_delete_this_question_question_tools_option() + self.sumo_pages.question_page.click_delete_this_question_button() + + self.navigate_to_link( + question_info_one['question_page_url'] + ) + + self.logger.info("Deleting the posted question") + self.sumo_pages.question_page.click_delete_this_question_question_tools_option() + self.sumo_pages.question_page.click_delete_this_question_button() + + # C2191264, C2191265 + # To add coverage for images as well + @pytest.mark.postedQuestions + @pytest.mark.parametrize("status", ['locked', 'archived']) + def test_lock_and_archive_this_question(self, status): + self.logger.info(f"Executing the {status} question tests") + self.logger.info("Signing in with a non admin user account") + self.start_existing_session(super().username_extraction_from_email( + self.user_secrets_accounts["TEST_ACCOUNT_13"] + )) + + self.logger.info("Posting a Firefox product question") + self.navigate_to_link(super().aaq_question_test_data["products_aaq_url"]["Firefox"]) + + question_info_one = self.sumo_pages.aaq_flow.submit_an_aaq_question_for_a_product( + subject=super().aaq_question_test_data["valid_firefox_question"]["subject"], + topic_name=self.sumo_pages.aaq_form_page.get_aaq_form_topic_options()[0], + body=super().aaq_question_test_data["valid_firefox_question"]["simple_body_text"], + attach_image=False + ) + + self.logger.info("Deleting user session") + self.delete_cookies() + + self.logger.info("Signing in with a different non admin user account") + self.start_existing_session(super().username_extraction_from_email( + self.user_secrets_accounts["TEST_ACCOUNT_12"] + )) + + self.logger.info("Posting a Firefox product question") + self.navigate_to_link(super().aaq_question_test_data["products_aaq_url"]["Firefox"]) + + question_info_two = self.sumo_pages.aaq_flow.submit_an_aaq_question_for_a_product( + subject=super().aaq_question_test_data["valid_firefox_question"]["subject"], + topic_name=self.sumo_pages.aaq_form_page.get_aaq_form_topic_options()[0], + body=super().aaq_question_test_data["valid_firefox_question"]["simple_body_text"], + attach_image=False + ) + + self.navigate_to_link( + question_info_one['question_page_url'] + ) + + if status == "locked": + self.logger.info("Verifying that the 'Lock this question' option is not available for " + "other posted questions") + expect( + self.sumo_pages.question_page.get_lock_this_question_locator() + ).to_be_hidden() + elif status == "archived": + expect( + self.sumo_pages.question_page.get_archive_this_question_locator() + ).to_be_hidden() + + self.navigate_to_link( + question_info_two['question_page_url'] + ) + + if status == "locked": + self.logger.info("Verifying that the 'Lock this question is not available for self " + "posted questions") + expect( + self.sumo_pages.question_page.get_lock_this_question_locator() + ).to_be_hidden() + elif status == "archived": + expect( + self.sumo_pages.question_page.get_archive_this_question_locator() + ).to_be_hidden() + + self.logger.info("Deleting session cookies and signing in with an admin account") + super().delete_cookies() + + self.start_existing_session(super().username_extraction_from_email( + self.user_secrets_accounts["TEST_ACCOUNT_MODERATOR"] + )) + + if status == "locked": + self.logger.info("Clicking on the 'Lock this question' option") + self.sumo_pages.question_page.click_on_lock_this_question_locator() + elif status == "archived": + self.logger.info("Clicking on the 'Archive this question' option") + self.sumo_pages.question_page.click_on_archive_this_question_option() + + self.logger.info("Deleting user session") + self.delete_cookies() + + self.logger.info("Signing in with a different non admin user account") + self.start_existing_session(super().username_extraction_from_email( + self.user_secrets_accounts["TEST_ACCOUNT_12"] + )) + + if status == "locked": + self.logger.info("Verifying that correct locked thread banner text is displayed") + check.equal( + self.sumo_pages.question_page.get_thread_locked_text(), + EditQuestionPageMessages.LOCKED_THREAD_BANNER + ) + elif status == "archived": + self.logger.info("Verifying that correct archived thread banner text is displayed") + check.equal( + self.sumo_pages.question_page.get_thread_locked_text(), + EditQuestionPageMessages.ARCHIVED_THREAD_BANNER + ) + + self.logger.info("Clicking on the locked thread link and verifying that we are " + "redirected to the correct page") + self.sumo_pages.question_page.click_on_thread_locked_link() + + expect( + self.page + ).to_have_url(ContactSupportMessages.PAGE_URL) + + self.logger.info("Navigating back to the question page") + self.navigate_back() + + if status == "locked": + self.logger.info("Verifying that the 'Unlock this question option is not available'") + expect( + self.sumo_pages.question_page.get_lock_this_question_locator() + ).to_be_hidden() + elif status == "archived": + expect( + self.sumo_pages.question_page.get_archive_this_question_locator() + ).to_be_hidden() + + self.logger.info("Verifying that the post a reply textarea field is not displayed") + expect( + self.sumo_pages.question_page.get_post_a_reply_textarea_locator() + ).to_be_hidden() + + self.logger.info("Verifying that the 'needs more information from the user' checkbox is " + "not displayed") + expect( + self.sumo_pages.question_page.get_needs_more_information_checkbox_locator() + ).to_be_hidden() + + self.logger.info("Verifying that the 'Add images section is not displayed'") + expect( + self.sumo_pages.question_page.get_add_image_section_locator() + ).to_be_hidden() + + self.logger.info("Deleting session cookies and signing in with an admin account") + super().delete_cookies() + + repliant_username = super().username_extraction_from_email( + self.user_secrets_accounts["TEST_ACCOUNT_MODERATOR"] + ) + + self.start_existing_session(super().username_extraction_from_email( + self.user_secrets_accounts["TEST_ACCOUNT_MODERATOR"] + )) + + self.logger.info("Adding text inside the textarea field") + self.sumo_pages.question_page.add_text_to_post_a_reply_textarea( + super().aaq_question_test_data['valid_firefox_question']['question_reply'] + ) + + self.logger.info("Verifying that the 'needs more information from the user' checkbox is " + "available") + expect( + self.sumo_pages.question_page.get_needs_more_information_checkbox_locator() + ).to_be_visible() + + self.logger.info("Verifying that the 'Add images' section is available") + expect( + self.sumo_pages.question_page.get_add_image_section_locator() + ).to_be_visible() + + self.logger.info("Clicking on the 'Post a reply button'") + reply_id = self.sumo_pages.question_page.click_on_post_reply_button(repliant_username) + + self.logger.info("Verifying that posted reply is visible") + expect( + self.sumo_pages.question_page.get_posted_reply_locator(reply_id) + ).to_be_visible() + + self.logger.info("Signing in with a normal user account and verifying that the admin's " + "reply is visible") + + self.logger.info("Deleting session cookies and signing in with an admin account") + super().delete_cookies() + + self.start_existing_session(super().username_extraction_from_email( + self.user_secrets_accounts["TEST_ACCOUNT_12"] + )) + + expect( + self.sumo_pages.question_page.get_posted_reply_locator(reply_id) + ).to_be_visible() + + self.logger.info("Deleting session cookies and signing in with an admin account") + super().delete_cookies() + + self.start_existing_session(super().username_extraction_from_email( + self.user_secrets_accounts["TEST_ACCOUNT_MODERATOR"] + )) + + if status == "locked": + self.logger.info("Unlocking the question") + self.sumo_pages.question_page.click_on_lock_this_question_locator() + elif status == "archived": + self.logger.info("Clicking on the 'Archive this question' option") + self.sumo_pages.question_page.click_on_archive_this_question_option() + + self.logger.info("Deleting session cookies and signing in with an admin account") + super().delete_cookies() + + second_repliant = super().username_extraction_from_email( + self.user_secrets_accounts["TEST_ACCOUNT_12"] + ) + self.start_existing_session(super().username_extraction_from_email( + self.user_secrets_accounts["TEST_ACCOUNT_12"] + )) + + self.logger.info("Verifying that the 'Thread locked' banner is not displayed") + expect( + self.sumo_pages.question_page.get_thread_locked_locator() + ).to_be_hidden() + + self.logger.info("Posting a question reply") + self.logger.info("Adding text inside the textarea field") + self.sumo_pages.question_page.add_text_to_post_a_reply_textarea( + super().aaq_question_test_data['valid_firefox_question']['question_reply'] + ) + + self.logger.info("Clicking on the 'Post a reply button'") + reply_id_two = self.sumo_pages.question_page.click_on_post_reply_button(second_repliant) + + self.logger.info("Verifying that the posted reply is visible") + + expect( + self.sumo_pages.question_page.get_posted_reply_locator(reply_id_two) + ).to_be_visible() + + self.logger.info("Deleting session cookies and signing in with an admin account") + super().delete_cookies() + + self.start_existing_session(super().username_extraction_from_email( + self.user_secrets_accounts["TEST_ACCOUNT_MODERATOR"] + )) + + self.logger.info("Deleting the posted question") + self.sumo_pages.question_page.click_delete_this_question_question_tools_option() + self.sumo_pages.question_page.click_delete_this_question_button() + + self.navigate_to_link( + question_info_one['question_page_url'] + ) + + self.logger.info("Deleting the posted question") + self.sumo_pages.question_page.click_delete_this_question_question_tools_option() + self.sumo_pages.question_page.click_delete_this_question_button() + + # C2191267, C2191116, C2134136, C2191091 + @pytest.mark.postedQuestions + def test_subscribe_to_feed_option(self): + self.logger.info("Signing in with a non admin user account") + self.start_existing_session(super().username_extraction_from_email( + self.user_secrets_accounts["TEST_ACCOUNT_13"] + )) + + self.logger.info("Posting a Firefox product question") + self.navigate_to_link(super().aaq_question_test_data["products_aaq_url"]["Firefox"]) + + question_info_one = self.sumo_pages.aaq_flow.submit_an_aaq_question_for_a_product( + subject=super().aaq_question_test_data["valid_firefox_question"]["subject"], + topic_name=self.sumo_pages.aaq_form_page.get_aaq_form_topic_options()[0], + body=super().aaq_question_test_data["valid_firefox_question"]["simple_body_text"], + attach_image=False + ) + + self.logger.info("Deleting user session") + self.delete_cookies() + + self.logger.info("Signing in with a different non admin user account") + self.start_existing_session(super().username_extraction_from_email( + self.user_secrets_accounts["TEST_ACCOUNT_12"] + )) + + self.logger.info("Posting a Firefox product question") + self.navigate_to_link(super().aaq_question_test_data["products_aaq_url"]["Firefox"]) + + question_info_two = self.sumo_pages.aaq_flow.submit_an_aaq_question_for_a_product( + subject=super().aaq_question_test_data["valid_firefox_question"]["subject"], + topic_name=self.sumo_pages.aaq_form_page.get_aaq_form_topic_options()[0], + body=super().aaq_question_test_data["valid_firefox_question"]["simple_body_text"], + attach_image=False + ) + + self.navigate_to_link( + question_info_one['question_page_url'] + ) + + self.logger.info("Clicking on the 'Subscribe to feed' option from different user posted " + "question") + if self.browser == "chrome": + self.sumo_pages.question_page.click_on_subscribe_to_feed_option() + self.logger.info("Verifying that the url is updated to the feed endpoint") + expect( + self.page + ).to_have_url( + question_info_one['question_page_url'] + EditQuestionPageMessages.FEED_FILE_PATH + ) + else: + with self.page.expect_download() as download_info: + self.sumo_pages.question_page.click_on_subscribe_to_feed_option() + download = download_info.value + + self.logger.info("Verifying that the received file contains the correct name") + check.is_in( + EditQuestionPageMessages.FEED_FILE_NAME, + download.suggested_filename, + f"Incorrect file name. " + f"Expected: {EditQuestionPageMessages.FEED_FILE_NAME} " + f"Received: {download.suggested_filename}" + ) + + self.logger.info("Verifying that the received file is not empty") + assert ( + os.path.getsize(download.path()) > 0 + ) + + self.navigate_to_link( + question_info_two['question_page_url'] + ) + if self.browser == "chrome": + self.sumo_pages.question_page.click_on_subscribe_to_feed_option() + self.logger.info("Verifying that the url is updated to the feed endpoint") + expect( + self.page + ).to_have_url( + question_info_two['question_page_url'] + EditQuestionPageMessages.FEED_FILE_PATH + ) + self.navigate_back() + else: + with self.page.expect_download() as download_info: + self.sumo_pages.question_page.click_on_subscribe_to_feed_option() + download = download_info.value + + self.logger.info("Verifying that the received file contains the correct name") + check.is_in( + EditQuestionPageMessages.FEED_FILE_NAME, + download.suggested_filename, + f"Incorrect file name. " + f"Expected: {EditQuestionPageMessages.FEED_FILE_NAME} " + f"Received: {download.suggested_filename}" + ) + + self.logger.info("Verifying that the received file is not empty") + assert ( + os.path.getsize(download.path()) > 0 + ) + + self.logger.info("Signing out") + super().delete_cookies() + + if self.browser == "chrome": + self.sumo_pages.question_page.click_on_subscribe_to_feed_option() + self.logger.info("Verifying that the url is updated to the feed endpoint") + expect( + self.page + ).to_have_url( + question_info_two['question_page_url'] + EditQuestionPageMessages.FEED_FILE_PATH + ) + self.navigate_back() + else: + with self.page.expect_download() as download_info: + self.sumo_pages.question_page.click_on_subscribe_to_feed_option() + download = download_info.value + + self.logger.info("Verifying that the received file contains the correct name") + check.is_in( + EditQuestionPageMessages.FEED_FILE_NAME, + download.suggested_filename, + f"Incorrect file name. " + f"Expected: {EditQuestionPageMessages.FEED_FILE_NAME} " + f"Received: {download.suggested_filename}" + ) + + self.logger.info("Verifying that the received file is not empty") + assert ( + os.path.getsize(download.path()) > 0 + ) + + self.logger.info("Signing in with an admin account") + + self.start_existing_session(super().username_extraction_from_email( + self.user_secrets_accounts["TEST_ACCOUNT_MODERATOR"] + )) + + if self.browser == "chrome": + self.sumo_pages.question_page.click_on_subscribe_to_feed_option() + self.logger.info("Verifying that the url is updated to the feed endpoint") + expect( + self.page + ).to_have_url( + question_info_two['question_page_url'] + EditQuestionPageMessages.FEED_FILE_PATH + ) + self.navigate_back() + else: + with self.page.expect_download() as download_info: + self.sumo_pages.question_page.click_on_subscribe_to_feed_option() + download = download_info.value + + self.logger.info("Verifying that the received file contains the correct name") + check.is_in( + EditQuestionPageMessages.FEED_FILE_NAME, + download.suggested_filename, + f"Incorrect file name. " + f"Expected: {EditQuestionPageMessages.FEED_FILE_NAME} " + f"Received: {download.suggested_filename}" + ) + + self.logger.info("Verifying that the received file is not empty") + assert ( + os.path.getsize(download.path()) > 0 + ) + + self.logger.info("Deleting the posted question") + self.sumo_pages.question_page.click_delete_this_question_question_tools_option() + self.sumo_pages.question_page.click_delete_this_question_button() + + self.navigate_to_link( + question_info_one['question_page_url'] + ) + + self.logger.info("Deleting the posted question") + self.sumo_pages.question_page.click_delete_this_question_question_tools_option() + self.sumo_pages.question_page.click_delete_this_question_button() + + # To work on adding a check inside the moderate forum content page + # C2191491 + @pytest.mark.postedQuestions + def test_mark_as_spam_functionality(self): + self.logger.info("Signing in with a non admin user account") + self.start_existing_session(super().username_extraction_from_email( + self.user_secrets_accounts["TEST_ACCOUNT_13"] + )) + + self.logger.info("Posting a Firefox product question") + self.navigate_to_link(super().aaq_question_test_data["products_aaq_url"]["Firefox"]) + + question_info = self.sumo_pages.aaq_flow.submit_an_aaq_question_for_a_product( + subject=super().aaq_question_test_data["valid_firefox_question"]["subject"], + topic_name=self.sumo_pages.aaq_form_page.get_aaq_form_topic_options()[0], + body=super().aaq_question_test_data["valid_firefox_question"]["simple_body_text"], + attach_image=False + ) + + self.logger.info("Deleting user session") + self.delete_cookies() + + self.logger.info("Verifying that the 'Mark as spam' option is not displayed") + expect( + self.sumo_pages.question_page.get_mark_as_spam_locator() + ).to_be_hidden() + + self.logger.info("Signing in with a non admin user account") + self.start_existing_session(super().username_extraction_from_email( + self.user_secrets_accounts["TEST_ACCOUNT_12"] + )) + + self.logger.info("Verifying that the 'Mark as spam' option is not displayed") + expect( + self.sumo_pages.question_page.get_mark_as_spam_locator() + ).to_be_hidden() + + self.logger.info("Deleting user session") + self.delete_cookies() + + username = super().username_extraction_from_email( + self.user_secrets_accounts["TEST_ACCOUNT_MODERATOR"] + ) + self.start_existing_session(super().username_extraction_from_email( + self.user_secrets_accounts["TEST_ACCOUNT_MODERATOR"] + )) + + self.logger.info("Clicking on the 'Mark as spam' option") + self.sumo_pages.question_page.click_on_mark_as_spam_option() + + self.logger.info("Verifying that the correct spam banner message is displayed") + check.is_in( + EditQuestionPageMessages.MARKED_AS_SPAM_BANNER + username, + self.sumo_pages.question_page.get_marked_as_spam_banner_text() + ) + + self.logger.info("Deleting user session") + self.delete_cookies() + + self.logger.info("Navigating to the posted question and verifying that the 404 is " + "returned while signed out") + with self.page.expect_navigation() as navigation_info: + self.navigate_to_link( + question_info['question_page_url'] + ) + response = navigation_info.value + check.equal( + response.status, + 404 + ) + + self.logger.info("Signing in with a non admin user account") + self.start_existing_session(super().username_extraction_from_email( + self.user_secrets_accounts["TEST_ACCOUNT_12"] + )) + + self.logger.info("Navigating to the posted question and verifying that 404 is returned") + with self.page.expect_navigation() as navigation_info: + self.navigate_to_link( + question_info['question_page_url'] + ) + response = navigation_info.value + check.equal( + response.status, + 404 + ) + + self.delete_cookies() + self.start_existing_session(super().username_extraction_from_email( + self.user_secrets_accounts["TEST_ACCOUNT_MODERATOR"] + )) + + self.logger.info("Clicking on the 'Mark as spam' option") + self.sumo_pages.question_page.click_on_mark_as_spam_option() + + self.logger.info("Verifying that the 'Marked as spam' banner is not displayed") + expect( + self.sumo_pages.question_page.get_marked_as_spam_banner_locator() + ).to_be_hidden() + + self.logger.info("Deleting user session") + self.delete_cookies() + + self.logger.info("Verifying that the 'Marked as spam' banner is not displayed") + expect( + self.sumo_pages.question_page.get_marked_as_spam_banner_locator() + ).to_be_hidden() + + self.logger.info("Signing in with a non admin user account") + self.start_existing_session(super().username_extraction_from_email( + self.user_secrets_accounts["TEST_ACCOUNT_12"] + )) + + self.logger.info("Verifying that the 'Marked as spam' banner is not displayed") + expect( + self.sumo_pages.question_page.get_marked_as_spam_banner_locator() + ).to_be_hidden() + + self.delete_cookies() + self.start_existing_session(super().username_extraction_from_email( + self.user_secrets_accounts["TEST_ACCOUNT_MODERATOR"] + )) + + self.logger.info("Deleting the posted question") + self.sumo_pages.question_page.click_delete_this_question_question_tools_option() + self.sumo_pages.question_page.click_delete_this_question_button() + + # C2191096 + @pytest.mark.postedQuestions + @pytest.mark.parametrize("username", ['', 'TEST_ACCOUNT_13']) + def test_question_topics(self, username): + self.logger.info("Signing in with a non admin user account") + self.start_existing_session(super().username_extraction_from_email( + self.user_secrets_accounts["TEST_ACCOUNT_12"] + )) + + self.logger.info("Posting a Firefox product question") + self.navigate_to_link(super().aaq_question_test_data["products_aaq_url"]["Firefox"]) + + question_info = self.sumo_pages.aaq_flow.submit_an_aaq_question_for_a_product( + subject=super().aaq_question_test_data["valid_firefox_question"]["subject"], + topic_name=self.sumo_pages.aaq_form_page.get_aaq_form_topic_options()[0], + body=super().aaq_question_test_data["valid_firefox_question"]["simple_body_text"], + attach_image=False + ) + + self.logger.info("Verifying that the 'Add a tag' input field is not displayed for OP") + expect( + self.sumo_pages.question_page.get_add_a_tag_input_field() + ).to_be_hidden() + + self.logger.info("Verifying that the 'Add' topic section button is not displayed for OP") + expect( + self.sumo_pages.question_page.get_add_a_tag_button() + ).to_be_hidden() + + self.logger.info("Deleting user session") + super().delete_cookies() + + if username == 'TEST_ACCOUNT_13': + self.logger.info("Signing in with a non admin user account") + self.start_existing_session(super().username_extraction_from_email( + self.user_secrets_accounts["TEST_ACCOUNT_13"] + )) + + self.logger.info("Verifying that the 'Add a tag' input field is not displayed") + expect( + self.sumo_pages.question_page.get_add_a_tag_input_field() + ).to_be_hidden() + + self.logger.info("Verifying that the 'Add' topic section button is not displayed") + expect( + self.sumo_pages.question_page.get_add_a_tag_button() + ).to_be_hidden() + + self.logger.info("Verifying that the remove tag button is not displayed") + for tag in self.sumo_pages.question_page.get_question_tag_options(): + expect( + self.sumo_pages.question_page.get_remove_tag_button_locator(tag) + ).to_be_hidden() + + if username == 'TEST_ACCOUNT_13': + super().delete_cookies() + + 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"] + )) + + self.logger.info("Adding data inside the 'Add a tag' input field and selecting the " + "option from the dropdown menu") + self.sumo_pages.question_page.add_text_to_add_a_tag_input_field( + super().aaq_question_test_data['valid_firefox_question']['custom_tag'] + ) + + self.logger.info("Clicking on the 'Add' button") + self.sumo_pages.question_page.click_on_add_a_tag_button() + + self.logger.info("Verifying that the newly added tag is displayed for all users") + super().delete_cookies() + + if username == 'TEST_ACCOUNT_13': + self.logger.info("Signing in with a non admin user account") + self.start_existing_session(super().username_extraction_from_email( + self.user_secrets_accounts["TEST_ACCOUNT_13"] + )) + + self.page.reload() + check.is_in( + super().aaq_question_test_data['valid_firefox_question']['custom_tag'], + self.sumo_pages.question_page.get_question_tag_options() + ) + + for question in self.sumo_pages.question_page.get_question_tag_options(): + self.logger.info(f"Clicking on the {question} tag") + self.sumo_pages.question_page.click_on_a_certain_tag(question) + self.logger.info("Verifying that the filter is applied to the clicked tag") + check.equal( + question, + self.sumo_pages.product_support_forum._get_text_of_selected_tag_filter_option() + ) + + self.logger.info("Verifying that each listed question inside the product forum " + "contains the filtered tab") + for article_id in self.sumo_pages.product_support_forum._extract_question_ids(): + check.is_in( + question, + self.sumo_pages.product_support_forum._get_all_question_list_tags(article_id) + ) + self.navigate_back() + + self.logger.info("Navigate back to the posted question") + self.navigate_to_link( + question_info['question_page_url'] + ) + + if username == 'TEST_ACCOUNT_13': + super().delete_cookies() + + 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"] + )) + + self.page.reload() + self.logger.info("Removing the newly added tag") + self.sumo_pages.question_page.click_on_tag_remove_button( + super().aaq_question_test_data['valid_firefox_question']['custom_tag'] + ) + + self.logger.info("Verifying that the tag was removed") + expect( + self.sumo_pages.question_page.get_a_certain_tag( + super().aaq_question_test_data['valid_firefox_question']['custom_tag'] + ) + ).to_be_hidden() + + self.logger.info("Deleting the user session") + super().delete_cookies() + + if username == "TEST_ACCOUNT_13": + self.logger.info("Signing in with a non admin user account") + self.start_existing_session(super().username_extraction_from_email( + self.user_secrets_accounts["TEST_ACCOUNT_13"] + )) + + self.logger.info("Verifying that the tag was removed") + expect( + self.sumo_pages.question_page.get_a_certain_tag( + super().aaq_question_test_data['valid_firefox_question']['custom_tag'] + ) + ).to_be_hidden() + + if username == "TEST_ACCOUNT_13": + super().delete_cookies() + + self.start_existing_session(super().username_extraction_from_email( + self.user_secrets_accounts["TEST_ACCOUNT_MODERATOR"] + )) + + self.logger.info("Deleting the posted question") + self.sumo_pages.question_page.click_delete_this_question_question_tools_option() + self.sumo_pages.question_page.click_delete_this_question_button() + + # C2191091 + @pytest.mark.postedQuestions + def test_email_updates_option_visibility(self): + self.logger.info("Signing in with a non admin user account") + self.start_existing_session(super().username_extraction_from_email( + self.user_secrets_accounts["TEST_ACCOUNT_13"] + )) + + self.logger.info("Posting a Firefox product question") + self.navigate_to_link(super().aaq_question_test_data["products_aaq_url"]["Firefox"]) + + self.sumo_pages.aaq_flow.submit_an_aaq_question_for_a_product( + subject=super().aaq_question_test_data["valid_firefox_question"]["subject"], + topic_name=self.sumo_pages.aaq_form_page.get_aaq_form_topic_options()[0], + body=super().aaq_question_test_data["valid_firefox_question"]["simple_body_text"], + attach_image=False + ) + + self.logger.info("Deleting user session") + self.delete_cookies() + + self.logger.info("Verifying that the 'Get email updates' option is displayed") + expect( + self.sumo_pages.question_page.get_email_updates_option() + ).to_be_visible() + + self.logger.info("Signing in with another non admin user account") + self.start_existing_session(super().username_extraction_from_email( + self.user_secrets_accounts["TEST_ACCOUNT_12"] + )) + + self.logger.info("Verifying that the 'Get email updates' option is displayed") + expect( + self.sumo_pages.question_page.get_email_updates_option() + ).to_be_visible() + + self.logger.info("Deleting user session") + super().delete_cookies() + + self.start_existing_session(super().username_extraction_from_email( + self.user_secrets_accounts["TEST_ACCOUNT_MODERATOR"] + )) + + self.logger.info("Verifying that the 'Get email updates' option is displayed") + expect( + self.sumo_pages.question_page.get_email_updates_option() + ).to_be_visible() + + self.logger.info("Deleting the posted question") + self.sumo_pages.question_page.click_delete_this_question_question_tools_option() + self.sumo_pages.question_page.click_delete_this_question_button() diff --git a/playwright_tests/tests/contribute_pages_tests/test_contribute_article_page.py b/playwright_tests/tests/contribute_pages_tests/test_contribute_article_page.py index 3673978f0..3ac670f07 100644 --- a/playwright_tests/tests/contribute_pages_tests/test_contribute_article_page.py +++ b/playwright_tests/tests/contribute_pages_tests/test_contribute_article_page.py @@ -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): diff --git a/playwright_tests/tests/popular_topics_page_tests/test_popular_topics_page.py b/playwright_tests/tests/popular_topics_page_tests/test_popular_topics_page.py index b39ee7fc3..eaf6e24e8 100644 --- a/playwright_tests/tests/popular_topics_page_tests/test_popular_topics_page.py +++ b/playwright_tests/tests/popular_topics_page_tests/test_popular_topics_page.py @@ -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) diff --git a/playwright_tests/tests/user_page_tests/test_edit_my_profile.py b/playwright_tests/tests/user_page_tests/test_edit_my_profile.py index 726968339..62f52d717 100644 --- a/playwright_tests/tests/user_page_tests/test_edit_my_profile.py +++ b/playwright_tests/tests/user_page_tests/test_edit_my_profile.py @@ -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