diff --git a/HQSmokeTests/testPages/android/android_screen.py b/HQSmokeTests/testPages/android/android_screen.py index cc4730a4d..4ded2439b 100644 --- a/HQSmokeTests/testPages/android/android_screen.py +++ b/HQSmokeTests/testPages/android/android_screen.py @@ -1,6 +1,7 @@ from appium import webdriver from selenium.webdriver.common.by import By from selenium.webdriver.support.wait import WebDriverWait +from selenium.webdriver.support import expected_conditions as ec from HQSmokeTests.userInputs.user_inputs import UserData from appium.options.android import UiAutomator2Options @@ -69,6 +70,7 @@ def __init__(self, settings): self.form = "//android.widget.TextView[@text='"+UserData.new_form_name+"']" self.text_field = "//android.widget.EditText" self.submit_button = "//android.widget.TextView[@text='FINISH']" + self.log_out = "//android.widget.TextView[@text='Log out of CommCare']" def click_xpath(self, locator): element = self.driver.find_element(AppiumBy.XPATH, locator) @@ -86,6 +88,11 @@ def send_text_id(self, locator, user_input): element = self.driver.find_element(AppiumBy.ID, locator) element.send_keys(user_input) + def wait_for_element(self, *locator, timeout=20): + clickable = ec.element_to_be_clickable(locator) + WebDriverWait(self.driver, timeout, poll_frequency=5).until(clickable, + message="Couldn't find locator: " + str(locator)) + def install_app_and_submit_form(self, code, random_text): self.driver.find_element(AppiumBy.XPATH, self.enter_code).click() self.driver.find_element(AppiumBy.ID, self.profile_code).send_keys(code) @@ -93,7 +100,7 @@ def install_app_and_submit_form(self, code, random_text): time.sleep(3) self.driver.find_element(AppiumBy.XPATH, self.install).click() time.sleep(15) - self.driver.find_element(AppiumBy.ID, self.username).send_keys(UserData.app_login) + self.driver.find_element(AppiumBy.ID, self.username).send_keys(UserData.new_app_login) self.driver.find_element(AppiumBy.ID, self.password).send_keys(UserData.app_password) self.driver.find_element(AppiumBy.ID, self.login).click() time.sleep(50) @@ -111,5 +118,50 @@ def install_app_and_submit_form(self, code, random_text): self.driver.find_element(AppiumBy.XPATH, self.sync_button).click() time.sleep(3) + def verify_app_install(self, code): + time.sleep(10) + self.driver.find_element(AppiumBy.XPATH, self.enter_code).click() + self.driver.find_element(AppiumBy.ID, self.profile_code).send_keys(code) + self.driver.find_element(AppiumBy.ID, self.start_install).click() + time.sleep(3) + self.driver.find_element(AppiumBy.XPATH, self.install).click() + time.sleep(30) + assert self.driver.find_element(AppiumBy.XPATH, "//android.widget.TextView[@text='Welcome back! Please log in.']").is_displayed(), "App not installed" + print("App installed successfully") + + def verify_login_with_old_password(self, code, username, password): + time.sleep(10) + self.driver.find_element(AppiumBy.XPATH, self.enter_code).click() + self.driver.find_element(AppiumBy.ID, self.profile_code).send_keys(code) + self.driver.find_element(AppiumBy.ID, self.start_install).click() + time.sleep(3) + self.driver.find_element(AppiumBy.XPATH, self.install).click() + time.sleep(30) + assert self.driver.find_element(AppiumBy.XPATH, "//android.widget.TextView[@text='Welcome back! Please log in.']").is_displayed(), "App not installed" + print("App installed successfully") + self.driver.find_element(AppiumBy.ID, self.username).send_keys(username) + self.driver.find_element(AppiumBy.ID, self.password).send_keys(password) + self.driver.find_element(AppiumBy.ID, self.login).click() + time.sleep(40) + self.driver.find_element(AppiumBy.XPATH, self.log_out).click() + print("Successfully logged in and logged out with old password:", username, password) + time.sleep(3) + assert self.driver.find_element(AppiumBy.XPATH, + "//android.widget.TextView[@text='Welcome back! Please log in.']" + ).is_displayed(), "App not installed" + + def verify_login_with_new_password(self, username, password): + time.sleep(30) + assert self.driver.find_element(AppiumBy.XPATH, "//android.widget.TextView[@text='Welcome back! Please log in.']").is_displayed(), "App not installed" + print("Welcome screen present") + self.driver.find_element(AppiumBy.ID, self.username).send_keys(username) + self.driver.find_element(AppiumBy.ID, self.password).send_keys(password) + self.driver.find_element(AppiumBy.ID, self.login).click() + time.sleep(40) + self.driver.find_element(AppiumBy.XPATH, self.log_out).click() + print("Successfully logged in and logged out with new password :", username, password) + time.sleep(3) + + def close_android_driver(self): self.driver.quit() diff --git a/HQSmokeTests/testPages/applications/application_page.py b/HQSmokeTests/testPages/applications/application_page.py index a5ebbb30b..9152f407d 100644 --- a/HQSmokeTests/testPages/applications/application_page.py +++ b/HQSmokeTests/testPages/applications/application_page.py @@ -83,6 +83,11 @@ def __init__(self, driver): self.advanced_settings_tab = (By.XPATH, "//a[@href='#commcare-settings']") self.advanced_settings_tab_content = (By.ID, "app-settings-options") self.form_settings_tab = (By.XPATH, "//a[@href='#form-settings']") + self.case_management_tab = (By.XPATH, "//a[@href='#case-configuration']") + self.user_properties = (By.XPATH, "//a[@href='#usercase-configuration']") + self.form_actions_tab = (By.XPATH, "//a[@href='#advanced']") + + # Form Field Edit self.add_new_form = (By.XPATH,"//a[@class='appnav-secondary js-add-new-item']") @@ -110,6 +115,8 @@ def __init__(self, driver): self.override_btn = (By.XPATH, "//button[contains(.,'Overwrite their work')]") self.enter_app_code_link = (By.LINK_TEXT, "Enter App Code") + + # language tab self.language_option = "//select[contains(@data-bind,'langcode')]/option[.='{}']" self.add_language_button = (By.XPATH, "//button[contains(@data-bind,'addLanguage')]") @@ -428,3 +435,35 @@ def delete_all_application(self, apps): self.click(self.delete_confirm) assert self.is_present_and_displayed(self.delete_success, 200), "Application "+app+" not deleted." print("Deleted the application", app) + + def verify_form_settings_page(self, form_name): + self.hover_on_element((By.XPATH, self.form_link.format(form_name))) + self.wait_to_click((By.XPATH, self.form_settings_btn.format(form_name))) + time.sleep(5) + assert self.is_present_and_displayed(self.form_settings_tab) + assert self.is_present_and_displayed(self.case_management_tab) + assert self.is_present_and_displayed(self.form_actions_tab) + assert self.is_present_and_displayed(self.user_properties) + print("Form Settings page correctly displayed") + + def verify_app_version_page(self): + self.wait_to_click((By.XPATH, self.field_edit_app_name.format(UserData.reassign_cases_application))) + time.sleep(2) + assert self.is_present_and_displayed(self.make_new_version_button) + print("Make New Version Page is correctly displayed") + + def get_app_code(self, app_name): + self.wait_to_click((By.XPATH, self.field_edit_app_name.format(app_name))) + time.sleep(2) + self.wait_for_element(self.make_new_version_button) + self.wait_to_click(self.publish_button) + if self.is_present_and_displayed(self.enter_app_code_link): + self.wait_to_click(self.enter_app_code_link) + else: + print("Enter App Code link is not present") + code_text = self.wait_to_get_text(self.code) + self.wait_to_click(self.close) + # self.wait_to_click(self.delete_form) + # self.wait_to_click(self.delete_form_confirm) + print("App code: ", code_text) + return code_text diff --git a/HQSmokeTests/testPages/data/copy_cases_page.py b/HQSmokeTests/testPages/data/copy_cases_page.py index a70ed2972..44c926372 100644 --- a/HQSmokeTests/testPages/data/copy_cases_page.py +++ b/HQSmokeTests/testPages/data/copy_cases_page.py @@ -1,6 +1,6 @@ import time -from selenium.webdriver import ActionChains +from selenium.webdriver import ActionChains, Keys from selenium.webdriver.common.by import By from common_utilities.selenium.base_page import BasePage from HQSmokeTests.userInputs.user_inputs import UserData @@ -16,9 +16,8 @@ def __init__(self, driver, settings): self.env_url = settings["url"] self.copy_cases_menu = (By.LINK_TEXT, "Copy Cases") self.apply = (By.ID, "apply-btn") - self.case_type = (By.XPATH, "//label[.='Case Type']//following-sibling::div/*[@class='select2 select2-container select2-container--default select2-container--below']") - self.case_type_dropdown = (By.XPATH, "//label[.='Case Type']//following-sibling::div/select[@name='case_type']") - + self.case_type = (By.XPATH, "//select[@name='case_type']") + self.case_type_option_value = (By.XPATH, "//option[@value='reassign']") self.select_first_case = (By.XPATH, "(//td[2][not(contains(.,'no name'))]//preceding-sibling::td/input[@type='checkbox'])[1]") self.first_case_name = (By.XPATH, "(//a[contains(@class, 'ajax_dialog')][not(contains(.,'no name'))])[1]") @@ -38,7 +37,9 @@ def __init__(self, driver, settings): self.copied_user_from_list = "//li[starts-with(text(), '{}')]" self.success_message = (By.XPATH, "//*[@data-bind='html: message' and contains(.,'Cases copied')]") self.empty_list = (By.XPATH, "//td[.='No data available to display. Please try changing your filters.']") - + self.users_field = (By.XPATH, "(//textarea[@class='select2-search__field'])[1]") + self.users_list_item = "//ul[@role='listbox']/li[contains(.,'{}')]" + self.remove_buttons = (By.XPATH, "//select[@name='case_list_filter']//following-sibling::span//ul//button") def sort_for_latest_on_top(self): self.wait_to_click(self.last_modified) @@ -47,14 +48,30 @@ def sort_for_latest_on_top(self): self.wait_to_click(self.last_modified) self.wait_for_element(self.last_modified_descending, 50) - def get_cases(self): + def remove_default_users(self): + self.wait_for_element(self.users_field) + count = self.find_elements(self.remove_buttons) + print(len(count)) + for i in range(len(count)): + count[0].click() + time.sleep(2) + if len(count) != 1: + ActionChains(self.driver).send_keys(Keys.TAB).perform() + time.sleep(2) + count = self.find_elements(self.remove_buttons) + ActionChains(self.driver).send_keys(Keys.ESCAPE).perform() + + def get_cases(self, username): self.wait_to_click(self.copy_cases_menu) - time.sleep(5) - self.wait_for_element(self.apply, 70) - self.select_by_text(self.user_search_dropdown, UserData.searched_user) - self.select_by_value(self.case_type_dropdown, UserData.case_pregnancy) + self.wait_for_element(self.case_type, 60) + self.select_by_value(self.case_type, UserData.case_reassign) + self.remove_default_users() + self.send_keys(self.users_field, username) + self.wait_to_click((By.XPATH, self.users_list_item.format(username))) + time.sleep(1) self.wait_to_click(self.apply) + def copy_case(self): self.sort_for_latest_on_top() time.sleep(5) @@ -66,20 +83,24 @@ def copy_case(self): time.sleep(1) assigned_username = self.get_text((By.XPATH,self.copied_user_from_list.format(UserData.mobile_testuser))) print("Assigned Username:", assigned_username) - self.move_to_element_and_click((By.XPATH,self.copied_user_from_list.format(UserData.mobile_testuser))) + self.move_to_element_and_click((By.XPATH, self.copied_user_from_list.format(UserData.mobile_testuser))) + time.sleep(5) self.wait_to_click(self.copy_btn) time.sleep(5) - self.wait_for_element(self.success_message, 30) + self.wait_for_element(self.success_message, 130) print("Sleeping for sometimes for the case to be copied") time.sleep(60) - self.wait_to_click(self.copy_cases_menu) + self.driver.refresh() time.sleep(5) - self.wait_for_element(self.apply, 70) - self.select_by_text(self.user_search_dropdown, assigned_username) + self.remove_default_users() + self.send_keys(self.users_field, assigned_username) + self.wait_to_click((By.XPATH, self.users_list_item.format(assigned_username))) + time.sleep(3) self.send_keys(self.search_query, case_being_copied) self.wait_to_click(self.apply) time.sleep(5) self.scroll_to_bottom() + self.sort_for_latest_on_top() if self.is_present(self.empty_list): print("No Case Copied, List is empty") assert False diff --git a/HQSmokeTests/testPages/data/export_data_page.py b/HQSmokeTests/testPages/data/export_data_page.py index 74d3ea035..9716f9cff 100644 --- a/HQSmokeTests/testPages/data/export_data_page.py +++ b/HQSmokeTests/testPages/data/export_data_page.py @@ -69,6 +69,7 @@ def __init__(self, driver): self.date_range = (By.ID, "id_date_range") self.close_date_picker = (By.XPATH, "//div[@data-action='close']") self.case_owner = (By.XPATH, "//span[@class='select2-selection select2-selection--multiple']") + self.export_sharing = (By.XPATH, "//select[@id='sharing-select']") # Export Form and Case data variables self.export_form_data_link = (By.LINK_TEXT, 'Export Form Data') @@ -169,6 +170,14 @@ def __init__(self, driver): os.path.join(UserData.USER_INPUT_BASE_DIR, "test_data/import_parent_child_case.xlsx") ) + self.repeat_checkbox = (By.XPATH, "//span[./span[@data-bind='text: table.label()'][contains(.,'Repeat') or contains(.,'repeat')]]//preceding-sibling::span/input[@type='checkbox'][contains(@data-bind,'disabled: false')]") + + # Shared Export + self.shared_export_name = "//div[@class='card-header'][.='Exports Shared with Me']//following-sibling::div//td[.//span[.='{}']]" + self.shared_export_view_button = "//td[.//span[.='{}']]//following-sibling::td//a[contains(@data-bind,'editUrl')]//span[contains(.,'View')][not(@style)]" + self.shared_export_edit_button = "//td[.//span[.='{}']]//following-sibling::td//a[contains(@data-bind,'editUrl')]//span[contains(.,'Edit')][not(@style)]" + + def get_url_paste_browser(self, username, password, item): if item == 'cases': odata_feed_link = self.wait_to_get_value(self.copy_odata_link_case) @@ -840,3 +849,97 @@ def verify_case_import(self, text): self.wait_for_element((By.XPATH, self.case_id_value.format(parent_id))) assert self.is_present(self.related_cases_tab), "Parent not reassigned" self.validate_child_case_data() + + def add_repeat_form_exports(self, app, case, form, export_name): + self.wait_for_element(self.add_export_button, 100) + self.delete_bulk_exports() + self.wait_and_sleep_to_click(self.add_export_button) + time.sleep(100) + self.is_visible_and_displayed(self.app_type, 200) + self.wait_for_element(self.app_type, 200) + self.is_clickable(self.app_type) + self.select_by_text(self.app_type, UserData.app_type) + self.select_by_text(self.application, app) + self.select_by_text(self.module, case) + self.select_by_text(self.form, form) + self.wait_to_click(self.add_export_conf) + self.wait_for_element(self.export_name, 200) + self.clear(self.export_name) + self.send_keys(self.export_name, export_name+Keys.TAB) + time.sleep(5) + self.scroll_to_bottom() + list_repeat = self.find_elements(self.repeat_checkbox) + if len(list_repeat) > 0: + assert True + else: + print("Repeat checkbox are either absent or not enabled") + assert False + time.sleep(5) + self.js_click(self.export_settings_create) + print("Export created!!") + + def check_for_case_id(self, case_id): + self.wait_for_element(self.find_data_by_ID) + self.wait_to_click(self.find_data_by_ID) + self.wait_to_clear_and_send_keys(self.find_data_by_case_ID_textbox, case_id) + self.wait_and_sleep_to_click(self.find_data_by_case_ID_button) + self.wait_for_element(self.view_FormID_CaseID) + link = self.get_attribute(self.view_FormID_CaseID, "href") + print(link) + self.driver.get(link) + self.wait_for_element((By.XPATH, self.case_id_value.format(case_id))) + if self.is_present_and_displayed((By.XPATH, self.case_id_value.format(case_id))): + assert True, "Case ID not present" + print("Case ID present") + else: + print("Case ID not present") + assert False + + def add_shared_form_exports(self, name, private='NO'): + self.wait_for_element(self.add_export_button, 100) + self.wait_and_sleep_to_click(self.add_export_button) + time.sleep(100) + self.is_visible_and_displayed(self.app_type, 200) + self.wait_for_element(self.app_type, 200) + self.is_clickable(self.app_type) + self.select_by_text(self.app_type, UserData.app_type) + self.select_by_text(self.application, UserData.village_application) + self.select_by_text(self.module, UserData.case_list_name) + self.select_by_text(self.form, UserData.form_name) + self.wait_to_click(self.add_export_conf) + self.wait_for_element(self.export_name, 200) + self.clear(self.export_name) + self.send_keys(self.export_name, name+Keys.TAB) + time.sleep(5) + if private == 'YES': + self.scroll_to_element(self.export_sharing) + self.select_by_value(self.export_sharing, 'private') + time.sleep(2) + else: + self.scroll_to_element(self.export_sharing) + self.select_by_value(self.export_sharing, 'edit_and_export') + time.sleep(2) + self.scroll_to_bottom() + time.sleep(5) + self.js_click(self.export_settings_create) + print("Export created!!") + time.sleep(10) + + def verify_shared_export_section(self, shared_export, private_export, permission='YES'): + self.wait_to_click(self.export_form_data_link) + self.wait_for_element(self.add_export_button) + assert self.is_present_and_displayed((By.XPATH, self.shared_export_name.format(shared_export))), "Shared export not present" + assert not self.is_present_and_displayed((By.XPATH, self.shared_export_name.format(private_export)), 5 + ), "Private export present" + if permission == 'YES': + assert self.is_present_and_displayed((By.XPATH, self.shared_export_edit_button.format(shared_export)) + ), "Shared export edit button not present" + assert not self.is_present_and_displayed((By.XPATH, self.shared_export_view_button.format(private_export)), 5 + ), "Shared export view button present" + elif permission == 'NO': + assert self.is_present_and_displayed((By.XPATH, self.shared_export_view_button.format(shared_export)) + ), "Shared export view button not present" + assert not self.is_present_and_displayed((By.XPATH, self.shared_export_edit_button.format(private_export)), 5 + ), "Shared export edit button present" + else: + print("Permission value is missing.") \ No newline at end of file diff --git a/HQSmokeTests/testPages/email/email_verification.py b/HQSmokeTests/testPages/email/email_verification.py index aaba96828..be5ac5b48 100644 --- a/HQSmokeTests/testPages/email/email_verification.py +++ b/HQSmokeTests/testPages/email/email_verification.py @@ -28,8 +28,8 @@ def get_hyperlink_from_latest_email(self, subject, url): with MailBox(self.imap_host).login(self.imap_user, self.imap_pass, 'INBOX') as mailbox: bodies = [msg.html for msg in - mailbox.fetch(AND(subject=subject, from_ =from_email, date=datetime.date.today()))] - soup = BeautifulSoup(str(bodies[len(bodies)-1]), "html.parser") + mailbox.fetch(AND(subject=subject, from_=from_email, date=datetime.date.today()))] + soup = BeautifulSoup(str(bodies[len(bodies) - 1]), "html.parser") links = [] for link in soup.findAll('a', attrs={'href': re.compile("^https://")}): links.append(link.get('href')) @@ -49,7 +49,7 @@ def get_email_body_from_latest_email(self, subject, url): print(subject) with MailBox(self.imap_host).login(self.imap_user, self.imap_pass, 'INBOX') as mailbox: bodies = [msg.html for msg in - mailbox.fetch(AND(subject=subject, from_=from_email, date=datetime.date.today()))] + mailbox.fetch(AND(subject=subject, from_=from_email, date=datetime.date.today()))] print(len(bodies)) n = '' end = -1 @@ -61,7 +61,7 @@ def get_email_body_from_latest_email(self, subject, url): end = None else: end = -1 - soup = BeautifulSoup(str(bodies[len(bodies)-1]), "html.parser") + soup = BeautifulSoup(str(bodies[len(bodies) - 1]), "html.parser") tr = [] table = [] @@ -88,7 +88,7 @@ def get_email_body_from_latest_email_proj_perf(self, subject, url): with MailBox(self.imap_host).login(self.imap_user, self.imap_pass, 'INBOX') as mailbox: bodies = [msg.html for msg in mailbox.fetch(AND(subject=subject, from_=from_email, date=datetime.date.today()))] - soup = BeautifulSoup(str(bodies[len(bodies)-1]), "html.parser") + soup = BeautifulSoup(str(bodies[len(bodies) - 1]), "html.parser") tr = [] td = [] table = [] @@ -128,7 +128,6 @@ def get_email_body_from_latest_email_proj_perf(self, subject, url): print("tab low", tab_low) - if len(table_inactive.findAll('td')) > 0: print(len(table_inactive.findAll('td'))) for row in table_inactive.select("tr"): @@ -183,4 +182,20 @@ def get_email_body_from_latest_email_proj_perf(self, subject, url): print("tab high", tab_high) table_data = [tab_low + tab_inactive + tab_high] - return table_data \ No newline at end of file + return table_data + + def verify_email_sent(self, subject, url): + if 'www' in url: + from_email = UserData.from_email_prod + elif 'india' in url: + from_email = UserData.from_email_india + else: + from_email = UserData.from_email + + with MailBox(self.imap_host).login(self.imap_user, self.imap_pass, 'INBOX') as mailbox: + for msg in mailbox.fetch( + AND(from_=from_email, date=datetime.date.today()) + ): + if msg.subject == subject: + print("Email is received") + assert True diff --git a/HQSmokeTests/testPages/home/home_page.py b/HQSmokeTests/testPages/home/home_page.py index c44c4a9a7..544fa67ae 100644 --- a/HQSmokeTests/testPages/home/home_page.py +++ b/HQSmokeTests/testPages/home/home_page.py @@ -138,3 +138,4 @@ def project_settings_page(self, value=None): self.js_click(self.project_settings_menu) assert self.PROJECT_SETTINGS == self.driver.title, "This is not the Project Settings page." print("Project Settings page loaded successfully!") + diff --git a/HQSmokeTests/testPages/messaging/messaging_page.py b/HQSmokeTests/testPages/messaging/messaging_page.py index 972a2c9e9..e1e80d2db 100644 --- a/HQSmokeTests/testPages/messaging/messaging_page.py +++ b/HQSmokeTests/testPages/messaging/messaging_page.py @@ -18,6 +18,7 @@ def __init__(self, driver): super().__init__(driver) self.cond_alert_name_input = "cond_alert_" + fetch_random_string() + self.cond_alert_no_value_name_input = "cond_alert_no_value_" + fetch_random_string() self.keyword_name_input = "KEYWORD_" + fetch_random_string().upper() self.struct_keyword_name_input = "STRUCTURED_KEYWORD_" + fetch_random_string().upper() self.broadcast_input = "broadcast_" + fetch_random_string() @@ -38,6 +39,7 @@ def __init__(self, driver): self.broadcasts = (By.LINK_TEXT, "Broadcasts") self.add_broadcast = (By.XPATH, "//div[@class='btn-group']") self.broadcast_name = (By.XPATH, "//input[@name='schedule-schedule_name']") + self.recipients_select_cond_alert = (By.XPATH, "//select[@name='schedule-recipient_types']") self.recipients = (By.XPATH, "(//span[@class='select2-selection select2-selection--multiple'])[1]") self.user_recipient = (By.XPATH, "(//span[@class='select2-selection select2-selection--multiple'])[2]") self.select_value_dropdown = (By.XPATH, "//ul[@class='select2-results__options']/li[.='"+UserData.app_login+"']") @@ -61,17 +63,15 @@ def __init__(self, driver): By.XPATH, "//case-property-input//span[@class='select2-selection select2-selection--single'][@role='combobox']") self.select_case_property = ( By.XPATH, "//select[@data-bind='value: valueObservable, autocompleteSelect2: casePropertyNames']") + self.select_match_type = (By.XPATH, "//select[@data-bind='value: match_type']") self.case_property_value = (By.XPATH, "//input[contains(@data-bind,'value: property_value')]") self.case_property_input = (By.XPATH, "//input[@class='select2-search__field']") self.continue_button_rule_tab = ( By.XPATH, "//button[@data-bind='click: handleRuleNavContinue, enable: ruleTabValid']") - self.cond_alert_created = (By.XPATH, "//a[text()='" + str(self.cond_alert_name_input) + "']") - self.restart_rule_button = (By.XPATH, "//td[./a[text()='" + str( - self.cond_alert_name_input) + "']]//following-sibling::td/div/button[contains(@data-bind,'restart')]") - self.restart_rule_button_none = (By.XPATH, "//td[./a[text()='" + str( - self.cond_alert_name_input) + "']]//following-sibling::td/div[@style='display: none;']/button[contains(@data-bind,'restart')]") - self.deactive_button_visible = (By.XPATH, "//td[./a[text()='" + str( - self.cond_alert_name_input) + "']]//following-sibling::td/button[contains(@data-bind,'toggleStatus')]/span[contains(@data-bind,'visible: active')]") + self.cond_alert_created = "//a[text()='{}']" + self.restart_rule_button = "//td[./a[text()='{}']]//following-sibling::td/div/button[contains(@data-bind,'restart')]" + self.restart_rule_button_none = "//td[./a[text()='{}']]//following-sibling::td/div[@style='display: none;']/button[contains(@data-bind,'restart')]" + self.deactive_button_visible = "//td[./a[text()='{}']]//following-sibling::td/button[contains(@data-bind,'toggleStatus')]/span[contains(@data-bind,'visible: active')]" self.empty_table_alert = ( By.XPATH, "//div[contains(@data-bind, 'emptyTable()')][contains(.,'There are no alerts to display')]") self.select_recipient_type = (By.XPATH, "//ul[@id='select2-id_schedule-recipient_types-results']/li[.='Users']") @@ -79,8 +79,7 @@ def __init__(self, driver): self.user_recipients_results = ( By.XPATH, "//ul[@id='select2-id_schedule-user_recipients-results']/li[.='" + UserData.app_login + "']") self.save_button_xpath = (By.XPATH, "//button[@type='submit'and text()='Save']") - self.delete_cond_alert = (By.XPATH, "//a[text()='" + str( - self.cond_alert_name_input) + "']//preceding::button[@class='btn btn-danger'][1]") + self.delete_cond_alert = "//a[text()='{}']//preceding::button[@class='btn btn-danger'][1]" self.search_box = (By.XPATH, "//form[@class='input-group']/input[@class='form-control']") self.search_btn = ( By.XPATH, "//form[@class='input-group']//button[@data-bind='click: clickAction, visible: !immediate']") @@ -243,13 +242,13 @@ def create_cond_alert(self): self.wait_to_clear_and_send_keys(self.search_box, self.cond_alert_name_input) time.sleep(10) self.wait_to_click(self.search_box) - self.wait_for_element(self.delete_cond_alert, 700) + self.wait_for_element((By.XPATH, self.delete_cond_alert.format(self.cond_alert_name_input)), 700) self.driver.refresh() - if self.is_clickable(self.delete_cond_alert): + if self.is_clickable((By.XPATH, self.delete_cond_alert.format(self.cond_alert_name_input))): print("Restart is not required.") else: try: - self.js_click(self.restart_rule_button) + self.js_click((By.XPATH, self.restart_rule_button.format(self.cond_alert_name_input))) self.accept_pop_up() time.sleep(5) self.accept_pop_up() @@ -257,14 +256,14 @@ def create_cond_alert(self): time.sleep(360) self.wait_to_clear_and_send_keys(self.search_box, self.cond_alert_name_input) self.wait_to_click(self.search_box) - self.wait_for_element(self.delete_cond_alert, 700) + self.wait_for_element((By.XPATH, self.delete_cond_alert.format(self.cond_alert_name_input)), 700) self.driver.refresh() except: print("Restart not required") self.wait_for_element(self.search_box) self.wait_to_clear_and_send_keys(self.search_box, self.cond_alert_name_input) self.wait_to_click(self.search_box) - assert self.is_displayed(self.cond_alert_created), "Conditional Alert not created successfully!" + assert self.is_displayed((By.XPATH, self.cond_alert_created.format(self.cond_alert_name_input))), "Conditional Alert not created successfully!" print("Conditional Alert created successfully!") return self.cond_alert_name_input @@ -498,9 +497,9 @@ def remove_cond_alert(self): self.driver.refresh() self.wait_to_clear_and_send_keys(self.search_box, self.cond_alert_name_input) self.wait_and_sleep_to_click(self.search_box) - self.wait_for_element(self.delete_cond_alert, 300) + self.wait_for_element((By.XPATH, self.delete_cond_alert.format(self.cond_alert_name_input)), 300) time.sleep(5) - self.wait_to_click(self.delete_cond_alert) + self.wait_to_click((By.XPATH, self.delete_cond_alert.format(self.cond_alert_name_input))) try: obj = self.driver.switch_to.alert obj.accept() @@ -511,7 +510,7 @@ def remove_cond_alert(self): self.driver.refresh() self.wait_to_clear_and_send_keys(self.search_box, self.cond_alert_name_input) self.wait_and_sleep_to_click(self.search_box) - isPresent = self.is_displayed(self.cond_alert_created) + isPresent = self.is_displayed((By.XPATH, self.cond_alert_created.format(self.cond_alert_name_input))) except NoSuchElementException: isPresent = False assert not isPresent @@ -524,7 +523,7 @@ def remove_alert_with_same_name(self, alert_name): if self.is_present_and_displayed(self.empty_table_alert): print("No alert created with the same name") else: - self.wait_to_click(self.delete_cond_alert) + self.wait_to_click((By.XPATH, self.delete_cond_alert.format(self.cond_alert_name_input))) try: obj = self.driver.switch_to.alert obj.accept() @@ -535,7 +534,7 @@ def remove_alert_with_same_name(self, alert_name): self.driver.refresh() self.wait_to_clear_and_send_keys(self.search_box, self.cond_alert_name_input) self.wait_and_sleep_to_click(self.search_box) - isPresent = self.is_displayed(self.cond_alert_created) + isPresent = self.is_displayed((By.XPATH, self.cond_alert_created.format(self.cond_alert_name_input))) except NoSuchElementException: isPresent = False assert not isPresent @@ -581,7 +580,6 @@ def current_subscription_page(self): self.subscription_elements_id), "Subscription Page did not load successfully" print("Current Subscription page loaded successfully!") - def remove_all_cond_alert(self): self.wait_to_click(self.cond_alerts) self.wait_for_element(self.value_per_page) @@ -606,3 +604,63 @@ def remove_all_cond_alert(self): else: print("No script created cond alerts present") print("All Cond Alert removed successfully!") + + def create_cond_alert_for_doesnot_have_value(self): + self.wait_to_click(self.cond_alerts) + self.remove_alert_with_same_name(self.cond_alert_no_value_name_input) + self.wait_to_click(self.add_cond_alert) + self.send_keys(self.cond_alert_name, self.cond_alert_no_value_name_input) + self.wait_to_click(self.continue_button_basic_tab) + time.sleep(2) + self.wait_to_click(self.case_type) + self.select_by_text(self.case_type, UserData.case_reassign) + time.sleep(3) + self.wait_to_click(self.select_filter) + self.wait_to_click(self.case_property_filter) + time.sleep(2) + self.wait_to_click(self.case_property_textbox) + time.sleep(1) + # self.send_keys(self.case_property_input, UserData.alert_case_property_random_value) + self.wait_for_element(self.select_case_property) + time.sleep(2) + self.select_by_text(self.select_case_property, UserData.alert_case_property_random_value) + self.select_by_text(self.select_match_type, UserData.alert_no_value) + self.wait_to_click(self.continue_button_rule_tab) + self.wait_for_element(self.recipients_select_cond_alert) + self.select_by_value(self.recipients_select_cond_alert, "Owner") + self.select_by_text(self.alert_type, "Email") + self.send_keys(self.email_subject, "Test Alert for no value" + self.cond_alert_no_value_name_input) + self.send_keys(self.broadcast_message, "Test Alert for no value:" + self.cond_alert_no_value_name_input) + self.wait_to_click(self.save_button_xpath) + print("Sleeping till the alert processing completes") + time.sleep(360) + self.driver.refresh() + time.sleep(160) + self.wait_to_clear_and_send_keys(self.search_box, self.cond_alert_no_value_name_input) + time.sleep(10) + self.wait_to_click(self.search_box) + self.wait_for_element((By.XPATH, self.delete_cond_alert.format(self.cond_alert_no_value_name_input)), 700) + self.driver.refresh() + if self.is_clickable((By.XPATH, self.delete_cond_alert.format(self.cond_alert_no_value_name_input))): + print("Restart is not required.") + else: + try: + self.js_click((By.XPATH, self.restart_rule_button.format(self.cond_alert_no_value_name_input))) + self.accept_pop_up() + time.sleep(5) + self.accept_pop_up() + print("Sleeping till the alert processing completes") + time.sleep(360) + self.wait_to_clear_and_send_keys(self.search_box, self.cond_alert_no_value_name_input) + self.wait_to_click(self.search_box) + self.wait_for_element((By.XPATH, self.delete_cond_alert.format(self.cond_alert_no_value_name_input)), 700) + self.driver.refresh() + except: + print("Restart not required") + self.wait_for_element(self.search_box) + self.wait_to_clear_and_send_keys(self.search_box, self.cond_alert_no_value_name_input) + self.wait_to_click(self.search_box) + assert self.is_displayed((By.XPATH, self.cond_alert_created.format(self.cond_alert_no_value_name_input))), "Conditional Alert not created successfully!" + print("Conditional Alert created successfully!") + subject = "Test Alert for no value" + self.cond_alert_no_value_name_input + return self.cond_alert_no_value_name_input, subject \ No newline at end of file diff --git a/HQSmokeTests/testPages/project_settings/repeaters_page.py b/HQSmokeTests/testPages/project_settings/repeaters_page.py index 5df0cc165..20e20bfa9 100644 --- a/HQSmokeTests/testPages/project_settings/repeaters_page.py +++ b/HQSmokeTests/testPages/project_settings/repeaters_page.py @@ -38,7 +38,10 @@ def __init__(self, driver): By.XPATH, "//div[contains(@class,'alert-success')][contains(.,'Forwarder Successfully Updated')]") self.delete_success = ( By.XPATH, "//div[contains(@class,'alert-success')][contains(.,'Forwarding stopped!')]") + self.close_message = ( + By.XPATH, "//div[contains(@class,'alert-success')][contains(.,'Forwarding stopped!')]/button[contains(@class,'close')]") self.confirm_delete_button = "//div[./p[contains(.,'{}')]]//following-sibling::div/*[contains(.,'Delete')]" + self.test_repeater_row = (By.XPATH, "//td[starts-with(.,'repeater_')]") def data_forwarding(self): self.wait_for_element(self.data_forwarding_linked_text) @@ -87,3 +90,24 @@ def delete_repeater(self): self.wait_to_click((By.XPATH, self.confirm_delete_button.format(self.repeater_name_input))) assert self.is_present_and_displayed(self.delete_success), "Delete repeater failed" print("Repeater deleted successfully") + + def delete_all_repeaters(self): + self.data_forwarding() + repeater_names = [] + list_repeater = self.find_elements(self.test_repeater_row) + if len(list_repeater) > 0: + print("Test repeaters are present") + for item in list_repeater: + repeater_names.append(item.text) + print("Test Repeater list: ", repeater_names) + for item in repeater_names: + self.wait_to_click((By.XPATH, self.repeater_delete_button.format(item))) + self.wait_for_element((By.XPATH, self.confirm_delete_button.format(item))) + self.wait_to_click((By.XPATH, self.confirm_delete_button.format(item))) + assert self.is_present_and_displayed(self.delete_success), "Delete repeater failed" + print("Repeater deleted successfully", item) + self.wait_to_click(self.close_message) + time.sleep(3) + print("All test repeaters deleted") + else: + print("No test repeaters present") diff --git a/HQSmokeTests/testPages/reports/report_page.py b/HQSmokeTests/testPages/reports/report_page.py index 21ed7cc42..ee4804c28 100644 --- a/HQSmokeTests/testPages/reports/report_page.py +++ b/HQSmokeTests/testPages/reports/report_page.py @@ -2,7 +2,6 @@ import time import html from datetime import datetime, timedelta -import re import pandas as pd from selenium.webdriver import ActionChains @@ -21,6 +20,45 @@ """"Contains test page elements and functions related to the Reports module""" +import re + + +def parse_time(time_str): + # Define regex patterns to match time units + time_units = { + 'days': 1, + 'weeks': 7, + 'months': 30, + 'years': 365 + } + + total_days = 0 + # Match days, weeks, months, and years in the string + for unit, multiplier in time_units.items(): + match = re.search(r'(\d+)\s+' + unit, time_str) + if match: + total_days += int(match.group(1)) * multiplier + + # If 'Never' is found, we return a very large value to consider it as the "oldest" + if 'Never' in time_str: + return float('inf') + + return total_days + + +def sort_times(time_list): + # Sort the list based on the parsed time values (newest first) + return sorted(time_list, key=parse_time, reverse=False) + + +def is_list_sorted_new_to_old(time_list): + # Parse each time string and check if they are in sorted order + parsed_times = [parse_time(time) for time in time_list] + res = all(parsed_times[i] >= parsed_times[i + 1] for i in range(len(parsed_times) - 1)) + print(res) + # Verify if the parsed times are sorted in descending order + return res + class ReportPage(BasePage): @@ -41,6 +79,7 @@ def __init__(self, driver): self.completion_vs_submission_rep = (By.LINK_TEXT, "Form Completion vs. Submission Trends") self.worker_activity_times_rep = (By.LINK_TEXT, "Worker Activity Times") self.project_performance_rep = (By.LINK_TEXT, "Project Performance") + self.CASE_LIST_TITLE = "Case List - CommCare HQ" # Inspect Data Reports self.submit_history_rep = (By.LINK_TEXT, "Submit History") @@ -83,6 +122,7 @@ def __init__(self, driver): self.select_source_id = (By.XPATH, "//select[@id='id_source']") self.select_form_type_value = "form" + self.select_case_type_value = "case" self.select_source_id_form_value = "Case List / Registration Form" self.select_source_id_case_value = "commcare-user" @@ -95,7 +135,7 @@ def __init__(self, driver): "(//a[text()='" + self.report_name_saved + "']//following::button[@class='btn btn-danger add-spinner-on-click'])[1]") self.delete_saved_report_link = "(//a[text()='{}']//following::button[@class='btn btn-danger add-spinner-on-click'])[1]" self.all_saved_reports = ( - By.XPATH, "//td[a[contains(.,'Saved')]]//following-sibling::td/button[contains(@data-bind,'delete')]") + By.XPATH, "//td[a[contains(.,'Saved')]]//following-sibling::td/button[contains(@data-bind,'delete')]") # Scheduled Reports self.scheduled_reports_menu_xpath = (By.XPATH, "//a[@href='#scheduled-reports']") @@ -127,6 +167,8 @@ def __init__(self, driver): self.case_type_select = (By.XPATH, "//select[@id='report_filter_case_type']") self.date_input = (By.XPATH, "//input[@id='filter_range']") self.view_form_link = (By.XPATH, "//tbody/tr[1]/td[1]/a[.='View Form']") + self.view_case_link = (By.XPATH, "//tbody/tr[1]/td[1]/a[.='View Case']") + self.case_name = (By.XPATH, "//td[div[contains(text(),'abc')]]") self.submit_history_table = (By.XPATH, "//table[@id='report_table_submit_history']/tbody/tr") self.location_values = (By.XPATH, "//tr[@class='form-data-question ']/td[2]") @@ -136,16 +178,36 @@ def __init__(self, driver): self.case_list_table = (By.XPATH, "//table[@id='report_table_case_list']/tbody/tr") self.case_id_block = (By.XPATH, "//th[@title='_id']/following-sibling::td") self.remove_case_owner = ( - By.XPATH, "//label[.='Case Owner(s)']//following-sibling::div//button[@aria-label='Remove item']") + By.XPATH, "//label[.='Case Owner(s)']//following-sibling::div//button[@aria-label='Remove item']") self.case_owner_textarea = (By.XPATH, "//label[.='Case Owner(s)']//following-sibling::div//textarea") self.case_owner_list_item = "//ul[@role='listbox']/li[contains(.,'{}')]" self.case_owner_column = (By.XPATH, "//tbody//td[3]") # Case List Explorer + self.query_div = (By.XPATH, "//div[@class='ace_content']//div[@class='ace_line']") + self.case_list_explorer_query_field = ( + By.XPATH, "//textarea[@class='ace_text-input']") + self.case_list_explorer_rep = (By.LINK_TEXT, "Case List Explorer") + self.case_list_explorer_TITLE = "Case List Explorer - CommCare HQ" + self.case_type_dropdown = (By.XPATH, "//select[@id='report_filter_case_type']") + self.column_editor = (By.XPATH, "//a[@href='#columns-editor']") + self.add_property_button = (By.XPATH, "//button[@data-bind='click: addProperty']") + self.last_properties_input = ( + By.XPATH, + "(//tbody[contains(@data-bind,'properties')]//td//input[contains(@data-bind,'Properties')])[last()]") + self.last_value_input = ( + By.XPATH, + "(//tbody[contains(@data-bind,'properties')]//td//input[contains(@data-bind,'value: label')])[last()]") + self.last_delete_property = (By.XPATH, "(//tbody[contains(@data-bind,'properties')]//td[4]/i)[last()]") + self.property_label = "//div[@class='atwho-container']//div[@class='atwho-view']//ul/li[1]/span[ .='reassign']//following-sibling::strong[.='name']" + self.properties_input = ( + By.XPATH, "//tbody[contains(@data-bind,'properties')]//td//input[contains(@data-bind,'Properties')]") + self.value_input = ( + By.XPATH, "//tbody[contains(@data-bind,'properties')]//td//input[contains(@data-bind,'value: label')]") + self.delete_property = (By.XPATH, "//tbody[contains(@data-bind,'properties')]//td[4]") self.edit_column = (By.XPATH, "//div[./label[contains(.,'Columns')]]//following-sibling::div//a[@data-parent='#case-list-explorer-columns']") self.properties_table = (By.XPATH, "//tbody[contains(@data-bind,'properties')]") - self.add_property_button = (By.XPATH, "//*[@data-bind='click: addProperty']") self.property_name_input = (By.XPATH, "(//tbody[contains(@data-bind,'properties')]//td[2]//input)[last()]") self.cle_case_owner_column = (By.XPATH, "//table[contains(@class,'datatable')]//tbody//td[5]") @@ -162,7 +224,7 @@ def __init__(self, driver): self.configurable_report = (By.LINK_TEXT, "Configurable Reports") self.add_report_button = (By.XPATH, "//div[@id='hq-content']//*[contains(.,'Add Report')]") self.edit_report_dropdown = ( - By.XPATH, "//span[contains(@class,'placeholder')][.='Edit a report or data source']") + By.XPATH, "//span[contains(@class,'placeholder')][.='Edit a report or data source']") self.report_search_input = (By.XPATH, "//input[@role='searchbox']") self.select_report = "//li[contains(.,'{}')]/i" self.report_dropdown = (By.XPATH, "//select[@id='select2-navigation']") @@ -173,19 +235,34 @@ def __init__(self, driver): self.daily_form_activity_results = (By.XPATH, "//table[@id='report_table_daily_form_stats']/tbody/tr") self.daily_form_activity_results_cells = (By.XPATH, "//table[@id='report_table_daily_form_stats']/tbody/tr/td") self.users_field = (By.XPATH, "(//textarea[@class='select2-search__field'])[1]") - self.remove_active_worker = (By.XPATH,"//span[.='[Active Mobile Workers]']//preceding-sibling::button[@class='select2-selection__choice__remove']") - self.remove_deactive_worker = (By.XPATH, "//span[.='[Deactivated Mobile Workers]']//preceding-sibling::button[@class='select2-selection__choice__remove']") + self.remove_active_worker = (By.XPATH, + "//span[.='[Active Mobile Workers]']//preceding-sibling::button[@class='select2-selection__choice__remove']") + self.remove_deactive_worker = (By.XPATH, + "//span[.='[Deactivated Mobile Workers]']//preceding-sibling::button[@class='select2-selection__choice__remove']") self.remove_buttons = (By.XPATH, "//ul//button") self.user_remove_btn = (By.XPATH, "(//button[@class='select2-selection__choice__remove'])[last()]") self.user_from_list = "//li[contains(.,'{}')]" self.export_to_excel = (By.XPATH, "//a[@id='export-report-excel']") self.export_success = (By.XPATH, "//span[.='Your requested Excel report will be sent to the email address defined in your account settings.']") + self.download_report_link = (By.XPATH, "//div[contains(@class,'success')]//a[.='Download Report']") # App Status - self.app_status_results = (By.XPATH, "//table[@class='table table-striped datatable dataTable no-footer']/tbody/tr") - self.app_status_results_cells = (By.XPATH, "//table[@class='table table-striped datatable dataTable no-footer']/tbody/tr/td") - + self.app_status_results = ( + By.XPATH, "//table[@class='table table-striped datatable dataTable no-footer']/tbody/tr") + self.app_status_results_cells = ( + By.XPATH, "//table[@class='table table-striped datatable dataTable no-footer']/tbody/tr/td") + self.panel_body_text = (By.XPATH, "//div[@class='panel-body-datatable']") + self.last_submit_column_list = (By.XPATH, "//table[@id='report_table_app_status']//tbody//td[3]") + self.last_submit_column_first = (By.XPATH, "(//table[@id='report_table_app_status']//tbody//td[3])[1]") + self.page_list_dropdown = (By.XPATH, "//select[@name='report_table_app_status_length']") + self.pagination_list = (By.XPATH, "//ul[@class='pagination']/li/a") + self.application_dropdown = (By.XPATH, "//select[@id='report_filter_app']") + self.application_field = (By.XPATH, "//span[contains(@id, 'report_filter_app-container')]") + self.application_input = (By.XPATH, "//input[contains(@aria-controls,'report_filter_app-result')]") + self.APPLICATION_STATUS_TITLE = "Application Status - CommCare HQ" + self.result_table = (By.XPATH, "(//div[@id='report-content']//table//tbody//td[1])[1]") + self.users_list_item = "//ul[@role='listbox']/li[contains(.,'{}')]" def check_if_report_loaded(self): try: @@ -280,13 +357,13 @@ def delete_report(self): def create_report_builder_case_report(self): self.wait_to_click(self.create_new_rep_id) self.send_keys(self.report_name_textbox_id, self.report_name_case) - self.click(self.select_app) + self.select_by_value(self.form_or_cases, self.select_case_type_value) + self.select_by_text(self.application, UserData.village_application) self.select_by_text(self.select_source_id, self.select_source_id_case_value) self.wait_to_click(self.next_button_id) self.wait_to_click(self.save_and_view_button_id) self.check_if_report_loaded() - def create_report_builder_form_report(self): self.wait_to_click(self.create_new_rep_id) self.send_keys(self.report_name_textbox_id, self.report_name_form) @@ -417,7 +494,6 @@ def delete_report_form_links(self): else: print("Report deleted successfully!") - def get_last_7_days_date_range(self): # Get today's date presentday = datetime.now() # or presentday = datetime.today() @@ -433,7 +509,8 @@ def get_todays_date_range(self): def verify_table_not_empty(self, locator): clickable = ec.presence_of_all_elements_located(locator) element = WebDriverWait(self.driver, 30).until(clickable, message="Couldn't find locator: " - + str(locator)) + + str(locator) + ) count = len(element) if count > 0: print(count, " rows are present in the web table") @@ -498,7 +575,7 @@ def verify_app_data_submit_history(self, case_name): self.wait_for_element(self.users_box, 300) self.wait_to_click(self.users_box) self.send_keys(self.search_user, UserData.app_login) - self.wait_to_click((By.XPATH, self.app_user_select.format(UserData.app_login))) + self.wait_to_click((By.XPATH, self.app_user_select.format(UserData.new_app_login))) self.select_by_text(self.application_select, UserData.reassign_cases_application) self.select_by_text(self.module_select, UserData.case_list_name) self.select_by_text(self.form_select, UserData.new_form_name) @@ -524,7 +601,8 @@ def verify_updated_data_in_case_list(self, case_name, value): time.sleep(3) self.page_source_contains(case_name) assert self.is_present_and_displayed( - (By.XPATH, "//div[@id='properties']//td[contains(text(),'" + value + "')]")), "Case property not updated." + (By.XPATH, "//div[@id='properties']//td[contains(text(),'" + value + "')]") + ), "Case property not updated." print("Case is updated successfully") case_id = self.get_text(self.case_id_block) return case_id @@ -660,7 +738,7 @@ def export_daily_form_activity_to_excel(self): ActionChains(self.driver).send_keys(Keys.TAB).perform() time.sleep(2) count = self.find_elements(self.remove_buttons) - # self.wait_to_click(self.users_field) + # self.wait_to_click(self.users_field) self.send_keys(self.users_field, UserData.app_login) self.wait_to_click((By.XPATH, self.user_from_list.format(UserData.app_login))) time.sleep(2) @@ -782,17 +860,15 @@ def compare_app_status_web_with_email(self, link, web_data): assert len(web_data) == len(list), "Data in Both Excel and Searched results do not match" print("Both Excel and Searched results have same amount of data") for i in range(len(list)): - if i == 1 or i == 2 or i == 3: - print("Not comparing", html.unescape(str(list[i])), " with ", str(web_data[i])) - else: - print("Comparing ", html.unescape(str(list[i])), " with ", str(web_data[i])) - assert html.unescape(str(list[i])) == str(web_data[i]), "Comparison failed for " + list[ - i] + " and " + web_data[i] + if i == 1 or i == 2 or i == 3: + print("Not comparing", html.unescape(str(list[i])), " with ", str(web_data[i])) + else: + print("Comparing ", html.unescape(str(list[i])), " with ", str(web_data[i])) + assert html.unescape(str(list[i])) == str(web_data[i]), "Comparison failed for " + list[ + i] + " and " + web_data[i] except Exception: print("No Data to compare or there is Data mismatch") - - def verify_form_in_submit_history(self, app_name, lat, lon): print("Sleeping for sometime for the case to get registered.") time.sleep(140) @@ -827,3 +903,132 @@ def format_number(self, n, digits): formatter = '{:.' + '{}'.format(digits) + 'f}' x = round(n, digits) return formatter.format(x) + + def verify_case_list_page(self): + self.wait_to_click(self.case_list_rep) + self.wait_for_element(self.apply_id, 100) + assert self.CASE_LIST_TITLE in self.driver.title, "This is not the Case List page." + text = self.get_text(self.panel_body_text) + print(text) + assert "Why can't I see any data?" in text + assert "Please choose your filters above and click Apply to see report data." in text + + def export_to_excel_config_report(self, report_name): + self.wait_to_click((By.LINK_TEXT, report_name)) + time.sleep(10) + self.wait_for_element(self.export_to_excel) + self.wait_to_click(self.export_to_excel) + self.wait_till_progress_completes("exports") + self.wait_to_click(self.download_report_link, 300) + print("Downloading report...") + time.sleep(3) + newest_file = latest_download_file() + print("Newest file:" + newest_file) + self.assert_downloaded_file(newest_file, report_name) + + def remove_default_users(self): + self.wait_for_element(self.users_field) + count = self.find_elements(self.remove_buttons) + print(len(count)) + for i in range(len(count)): + count[0].click() + time.sleep(2) + if len(count) != 1: + ActionChains(self.driver).send_keys(Keys.TAB).perform() + time.sleep(2) + count = self.find_elements(self.remove_buttons) + ActionChains(self.driver).send_keys(Keys.ESCAPE).perform() + + def verify_sorted_list(self): + self.select_by_value(self.page_list_dropdown, '100') + time.sleep(10) + list1 = self.find_elements(self.last_submit_column_list) + list1_names = list() + for item in list1: + list1_names.append(item.text) + print(list1_names) + sorted_time_list = sort_times(list1_names) + print(sorted_time_list) + if list1_names == sorted_time_list: + assert True + else: + assert False + # result = is_list_sorted_new_to_old(list1_names) + # print(result) + + def application_status_report_search(self): + self.wait_to_click(self.application_status_rep) + self.wait_for_element(self.apply_id, 100) + assert self.APPLICATION_STATUS_TITLE in self.driver.title, "This is not the Application Status page." + self.remove_default_users() + self.click(self.application_field) + self.send_keys(self.application_input, UserData.reassign_cases_application) + self.wait_to_click((By.XPATH, self.users_list_item.format(UserData.reassign_cases_application))) + time.sleep(2) + self.wait_to_click(self.apply_id) + time.sleep(10) + self.wait_for_element(self.result_table, 300) + assert self.is_visible_and_displayed(self.report_content_id, 120), "Report not loaded" + print("Report loaded successfully!") + + def verify_case_list_explorer_properties(self): + self.wait_to_click(self.case_list_explorer_rep) + self.wait_for_element(self.apply_id, 100) + assert self.case_list_explorer_TITLE in self.driver.title, "This is not the Case List Explorer page." + self.select_by_value(self.case_type_dropdown, UserData.case_reassign) + return UserData.case_reassign + + def add_new_property(self, name): + self.scroll_to_element(self.column_editor) + self.wait_to_click(self.column_editor) + props1 = self.find_elements(self.properties_input) + value1 = self.find_elements(self.value_input) + delete1 = self.find_elements(self.delete_property) + assert len(props1) != 0, "Property fields not present" + assert len(value1) != 0, "Value fields not present" + assert len(delete1) != 0, "Delete fields not present" + self.wait_for_element(self.add_property_button) + self.wait_to_click(self.add_property_button) + time.sleep(2) + assert len(props1) + 1 == len(self.find_elements(self.properties_input)), "Property fields not added" + assert len(value1) + 1 == len(self.find_elements(self.value_input)), "Value fields not added" + assert len(delete1) + 1 == len(self.find_elements(self.delete_property)), "Delete fields not added" + self.send_keys(self.last_properties_input, "name") + time.sleep(2) + if self.is_visible_and_displayed((By.XPATH, self.property_label.format(name))): + assert True + print("Property present") + else: + print("Property absent") + assert False + ActionChains(self.driver).send_keys(Keys.TAB).perform() + + def get_case_id_from_case_list_explorer(self, text): + query = "case_name = '" + text + "'" + self.wait_to_click(self.case_list_explorer_rep) + self.wait_for_element(self.apply_id, 100) + self.remove_default_users() + self.js_click(self.query_div) + time.sleep(2) + self.send_keys(self.case_list_explorer_query_field, query) + time.sleep(2) + self.select_by_text(self.case_type_dropdown, UserData.case_reassign_change) + time.sleep(2) + self.scroll_to_element(self.apply_id) + self.js_click(self.apply_id) + time.sleep(5) + self.wait_for_element(self.result_table, 300) + assert self.is_visible_and_displayed(self.report_content_id, 120), "Report not loaded" + print("Report loaded successfully!") + form_link = self.get_attribute(self.view_case_link, "href") + print("View Form Link: ", form_link) + # self.switch_to_new_tab() + self.driver.get(form_link) + time.sleep(3) + self.page_source_contains(text) + assert True, "Case name is present in Submit history" + self.page_source_contains(text) + print("Case is updated successfully") + case_id = self.get_text(self.case_id_block) + return case_id + diff --git a/HQSmokeTests/testPages/users/mobile_workers_page.py b/HQSmokeTests/testPages/users/mobile_workers_page.py index ed7d160b0..39099ad57 100644 --- a/HQSmokeTests/testPages/users/mobile_workers_page.py +++ b/HQSmokeTests/testPages/users/mobile_workers_page.py @@ -4,7 +4,7 @@ import pandas as pd from openpyxl import load_workbook -from selenium.webdriver import Keys +from selenium.webdriver import Keys, ActionChains from common_utilities.selenium.base_page import BasePage from common_utilities.path_settings import PathSettings @@ -161,6 +161,15 @@ def __init__(self, driver): self.location_combobox = (By.XPATH, "//span[@class='select2-selection select2-selection--multiple']") self.location_selection = (By.XPATH, "//li[contains(text(),'updated')]") self.location_update_button = (By.XPATH, "//button[contains(text(),'Update Location Settings')]") + self.remove_assigned_location = (By.XPATH, "//select[@name='assigned_locations']//following-sibling::span//ul//button") + self.assigned_location_field = (By.XPATH, "(//textarea[@class='select2-search__field'])[1]") + + # Reset Password + self.security_tab = (By.XPATH, "//a[@href='#user-password']") + self.password_field = (By.XPATH, "//input[@name='new_password1']") + self.confirm_password_field = (By.XPATH, "//input[@name='new_password2']") + self.reset_button_xpath = (By.XPATH, '//*[@type="submit"][contains(@value,"Reset")]') + # Download and Upload self.download_worker_btn = (By.LINK_TEXT, "Download Mobile Workers") @@ -178,6 +187,9 @@ def __init__(self, driver): self.no_user_found = (By.XPATH, "//text()[contains(.,'No users found')]") self.role_dropdown = (By.XPATH, "//select[@id='id_role']") + self.loaction_page_alert_info = (By.XPATH, "//div[contains(@class,'alert-info')]/p[contains(.,'The user shares all assigned locations with one or more other users.')]") + + def search_user(self, username): self.wait_to_clear_and_send_keys(self.search_mw, username) @@ -695,3 +707,33 @@ def verify_profile_change(self, profile): text = self.get_selected_text(self.profile_dropdown) print(text) assert text == profile, "Profile is not the same as set before upload" + + + def remove_location(self): + self.wait_to_click(self.location_tab) + self.wait_for_element(self.assigned_location_field) + count = self.find_elements(self.remove_assigned_location) + print(len(count)) + for i in range(len(count)): + count[0].click() + time.sleep(2) + if len(count) != 1: + ActionChains(self.driver).send_keys(Keys.TAB).perform() + time.sleep(2) + count = self.find_elements(self.remove_assigned_location) + ActionChains(self.driver).send_keys(Keys.ESCAPE).perform() + + def verify_location_alert_not_present(self): + assert not self.is_present_and_displayed(self.loaction_page_alert_info, 10), "Location alert banner present" + print("Location alert button not present") + + def reset_mobile_worker_password(self, new): + self.wait_for_element(self.security_tab) + self.wait_to_click(self.security_tab) + self.wait_for_element(self.password_field) + self.send_keys(self.password_field, new) + time.sleep(1) + self.send_keys(self.confirm_password_field, new) + self.wait_to_click(self.reset_button_xpath) + self.wait_for_element(self.user_field_success_msg, 30) + print("Password reset successfully") \ No newline at end of file diff --git a/HQSmokeTests/testPages/users/roles_permissions_page.py b/HQSmokeTests/testPages/users/roles_permissions_page.py index ba3a9543f..7d2c536d0 100644 --- a/HQSmokeTests/testPages/users/roles_permissions_page.py +++ b/HQSmokeTests/testPages/users/roles_permissions_page.py @@ -22,6 +22,8 @@ def __init__(self, driver, settings): self.role_name_created = "role_" + fetch_random_string() self.role_non_admin_created = "role_non_" + fetch_random_string() + self.role_no_shared_export_created = "role_no_export_" + fetch_random_string() + self.role_yes_shared_export_created = "role_yes_export_" + fetch_random_string() self.role_rename_created = "role_rename_" + fetch_random_string() self.roles_menu = (By.XPATH, "//a[@data-title='Roles & Permissions']") self.add_new_role = ( @@ -35,13 +37,20 @@ def __init__(self, driver, settings): self.delete_role = (By.XPATH, "//th[.//span[.='" + str( self.role_name_created) + "']]/following-sibling::td//i[@class='fa fa-trash']") self.edit_mobile_worker_checkbox = (By.XPATH, "//input[@id='edit-commcare-users-checkbox']") + self.manage_shared_exports = (By.XPATH, "//input[@id='edit-shared-exports-checkbox']") + self.data_checkbox = (By.XPATH, "//input[@id='edit-data-checkbox']") + self.report_for_p1p2 = (By.XPATH, "//div[contains(@data-bind,'reportPermission')]//label[./span[.='"+UserData.report_for_p1p2+"']]") self.role_renamed = (By.XPATH, "//span[text()='" + str(self.role_rename_created) + "']") self.role_non_admin = (By.XPATH, "//span[text()='" + str(self.role_non_admin_created) + "']") + self.role_no_shared_export = "//span[text()='{}']" self.confirm_role_delete = (By.XPATH, "//div[@class='btn btn-danger']") self.full_org_access_checkbox = (By.XPATH, "//label[contains(.,'Full Organization Access')]//following-sibling::div//input") self.access_all_reports_checkbox = (By.XPATH, "//input[@id='access-all-reports-checkbox']") + self.web_user_permission = "//th[./span[.='{}']]//following-sibling::td/div[contains(@data-bind,'edit_web_users')]/i[contains(@class,'check')]" + self.mobile_worker_permission = "//th[./span[.='{}']]//following-sibling::td/div[contains(@data-bind,'edit_commcare_users')]/i[contains(@class,'check')]" + self.managed_shared_export_permission = "//th[./span[.='{}']]//following-sibling::td/div[contains(@data-bind,'edit_shared_exports')]/i[contains(@class,'check')]" def roles_menu_click(self): self.wait_to_click(self.roles_menu) @@ -142,4 +151,37 @@ def add_non_admin_role(self): self.click(self.save_button) time.sleep(2) assert self.is_present_and_displayed(self.role_non_admin), "Role not added successfully!" - return self.role_non_admin_created \ No newline at end of file + return self.role_non_admin_created + + + def add_shared_export_role(self, name, flag='NO'): + self.wait_to_click(self.add_new_role) + self.wait_to_clear_and_send_keys(self.role_name, name) + time.sleep(1) + self.click(self.edit_mobile_worker_checkbox) + time.sleep(0.5) + self.click(self.edit_web_user_checkbox) + time.sleep(0.5) + self.click(self.data_checkbox) + time.sleep(0.5) + self.scroll_to_element(self.manage_shared_exports) + if flag == 'YES': + time.sleep(2) + self.click(self.manage_shared_exports) + time.sleep(2) + time.sleep(0.5) + self.scroll_to_element(self.access_all_reports_checkbox) + time.sleep(1) + self.click(self.access_all_reports_checkbox) + time.sleep(0.5) + self.scroll_to_element(self.save_button) + time.sleep(0.5) + self.click(self.save_button) + time.sleep(2) + assert self.is_present_and_displayed((By.XPATH, self.role_no_shared_export.format(name))), "Role not added successfully!" + assert self.is_present_and_displayed((By.XPATH, self.web_user_permission.format(name))), "Web User Permission not present" + assert self.is_present_and_displayed((By.XPATH, self.mobile_worker_permission.format(name))), "Mobile Worker Permission not present" + if flag == "NO": + assert not self.is_present_and_displayed((By.XPATH, self.managed_shared_export_permission.format(name)), 5), "Shared Export Permission is present" + else: + assert self.is_present_and_displayed((By.XPATH, self.managed_shared_export_permission.format(name))), "Shared Export Permission not present" diff --git a/HQSmokeTests/testPages/users/web_user_page.py b/HQSmokeTests/testPages/users/web_user_page.py index 3a603c7bc..64d1b5991 100644 --- a/HQSmokeTests/testPages/users/web_user_page.py +++ b/HQSmokeTests/testPages/users/web_user_page.py @@ -202,4 +202,16 @@ def edit_user_permission(self, rolename): self.wait_to_click(self.update_location_btn) time.sleep(2) - + def change_user_role(self, username, role): + self.wait_to_click(self.web_users_menu) + self.wait_for_element(self.search_user) + self.wait_to_clear_and_send_keys(self.search_user, username) + time.sleep(1) + self.wait_to_click(self.search_user_btn) + time.sleep(2) + self.wait_for_element(self.user_link) + self.wait_to_click(self.user_link) + self.wait_for_element(self.select_project_role_id) + self.select_by_text(self.select_project_role_id, role) + self.wait_to_click(self.update_role_btn) + time.sleep(2) diff --git a/HQSmokeTests/testPages/webapps/web_apps_page.py b/HQSmokeTests/testPages/webapps/web_apps_page.py index bf6fd768d..2b2ce490b 100644 --- a/HQSmokeTests/testPages/webapps/web_apps_page.py +++ b/HQSmokeTests/testPages/webapps/web_apps_page.py @@ -20,6 +20,7 @@ def __init__(self, driver): self.case_name_created = "case_" + fetch_random_string() self.text_value = "text_" + fetch_random_string() + self.form_text_value = "cond_alert_" + fetch_random_string() self.random_value = fetch_random_digit() self.login_as_css = (By.CLASS_NAME, "js-restore-as-item") @@ -28,7 +29,7 @@ def __init__(self, driver): self.sync_button = (By.XPATH, "//h3[.='Sync']") self.home_button = (By.XPATH, "//li[contains(@class,'home')]") self.apps_links = (By.XPATH, "//*[@class='fcc fcc-flower appicon-icon']") - self.web_app_link = (By.XPATH, "//*[text()='" + UserData.reassign_cases_application + "']") + self.web_app_link = (By.XPATH, "//div[@class='appicon-title']//*[text()='" + UserData.reassign_cases_application + "']") self.case_list_link = (By.XPATH, "//*[text()='" + UserData.case_list_name + "']") self.update_case_change_link = (By.XPATH, "//*[text()='" + UserData.update_case_change_link + "']") self.case_register_form = (By.XPATH, "//*[text()='" + UserData.case_register_form + "']") @@ -121,3 +122,22 @@ def submit_case_update_form(self, case_name): def click_case_link(self): case_link = self.get_attribute(self.this_case, "href") self.driver.get(case_link) + + def submit_case_change_register_form_no_value(self): + self.scroll_to_element(self.web_app_link) + time.sleep(3) + # self.wait_for_element(self.web_app_link) + self.js_click(self.web_app_link) + self.wait_for_element(self.update_case_change_link) + self.js_click(self.update_case_change_link) + self.wait_for_element(self.case_register_form) + self.js_click(self.case_register_form) + self.wait_to_clear_and_send_keys(self.enter_text_area, self.form_text_value) + self.js_click(self.form_submit_button) + self.wait_for_ajax() + time.sleep(5) + self.wait_for_element(self.success_message) + assert self.is_displayed(self.success_message), "Form not submitted" + print("Form successfully submitted") + print(self.form_text_value) + return self.form_text_value diff --git a/HQSmokeTests/userInputs/user_inputs.py b/HQSmokeTests/userInputs/user_inputs.py index d6ff74492..b8eb1ff44 100644 --- a/HQSmokeTests/userInputs/user_inputs.py +++ b/HQSmokeTests/userInputs/user_inputs.py @@ -11,10 +11,12 @@ class UserData: reassign_cases_application = 'Reassign Cases' case_pregnancy = "pregnancy" case_reassign = "reassign" + case_reassign_change = "reassign_change" model_type_case = "case" model_type_form = "form" new_form_name = "Android Test Form" app_login = "appiumtest" + new_app_login = "apptest" app_password = "Pass@123" two_fa_user = "2fa.commcare.user@gmail.com" web_user = "[Web Users]" @@ -77,7 +79,8 @@ class UserData: """Conditional Alert""" alert_case_property = "name" alert_case_property_value = "conditional alert" - + alert_case_property_random_value = "enter_a_random_value" + alert_no_value = "does not have a value" """Saved report""" report_for_p1p2 = "Report For P1P2" @@ -104,3 +107,6 @@ class UserData: parent_type = "pregnancy" child_type = "village" child_name = "Saharanpur" + + private_export_yes = "Smoke Shared Form Export" + private_export_no = "Smoke Shared Private Form Export" \ No newline at end of file diff --git a/LocustScripts/update-scripts/commcarehq-referrals-search-for-beds-mw-login_single_case.py b/LocustScripts/update-scripts/commcarehq-referrals-search-for-beds-mw-login_single_case.py index fccd97506..fd2d2859d 100644 --- a/LocustScripts/update-scripts/commcarehq-referrals-search-for-beds-mw-login_single_case.py +++ b/LocustScripts/update-scripts/commcarehq-referrals-search-for-beds-mw-login_single_case.py @@ -43,6 +43,7 @@ def on_start(self): self.FUNC_ENTER_GENDER = APP_CONFIG["FUNC_ENTER_GENDER"] self.FUNC_OUTGOING_REFERRAL_DETAILS_FORM = APP_CONFIG["FUNC_OUTGOING_REFERRAL_DETAILS_FORM"] self.FUNC_OUTGOING_REFERRAL_DETAILS_FORM_SUBMIT = APP_CONFIG["FUNC_OUTGOING_REFERRAL_DETAILS_FORM_SUBMIT"] + self.FUNC_OPEN_BEDS = APP_CONFIG['FUNC_OPEN_BEDS'] self.cases_per_page = 100 @tag('home_screen') @@ -64,6 +65,26 @@ def search_for_beds_menu(self): if data: self.page_count = data["pageCount"] + @tag('open_bed_search') + @task + def open_bed_search(self): + logging.info( + "Searching open beds for - mobile worker:" + self.user.user_detail.username + "; request: navigate_menu" + ) + data = { + "query_data": { + "m2_results.inline": { + "inputs": { + self.FUNC_OPEN_BEDS['input']: self.FUNC_OPEN_BEDS['inputValue'] + }, + "execute": True + } + }, + "selections": ["0"], + } + self.user.hq_user.navigate("Perform a bed search", data=data) + + @tag('select_cases') @task def select_cases(self): diff --git a/LocustScripts/update-scripts/project-config/co-carecoordination-perf/app_config_referrals_platform.json b/LocustScripts/update-scripts/project-config/co-carecoordination-perf/app_config_referrals_platform.json index 3df2045ef..c1a58fe01 100644 --- a/LocustScripts/update-scripts/project-config/co-carecoordination-perf/app_config_referrals_platform.json +++ b/LocustScripts/update-scripts/project-config/co-carecoordination-perf/app_config_referrals_platform.json @@ -3,7 +3,10 @@ "title":"Client Care Search" }, "FUNC_SEARCH_FOR_BEDS_MENU": { - "selections":"1", "title":"Pilot: Submit Referrals" + "selections":"0", "title":"Send Referrals" + }, + "FUNC_OPEN_BEDS": { + "selections":"0", "input":"only_open_beds", "inputValue":"yes" }, "FUNC_OUTGOING_REFERRALS_MENU": { "selections":"4", "title": "Search Outgoing Referrals" diff --git a/MobileTest/QA_7315/20240422-app-cccStaging-release.apk b/MobileTest/QA_7315/20240422-app-cccStaging-release.apk new file mode 100644 index 000000000..206ec51d1 Binary files /dev/null and b/MobileTest/QA_7315/20240422-app-cccStaging-release.apk differ diff --git a/MobileTest/QA_7315/README.md b/MobileTest/QA_7315/README.md new file mode 100644 index 000000000..646bce8d6 --- /dev/null +++ b/MobileTest/QA_7315/README.md @@ -0,0 +1,54 @@ +## Bulk Form Submission Appium Test Script + +This test script is used to validate that the test the above "over total limit" labels in CCC without having to submit 60 Infant Immunization Record forms in the app. + +## Executing Scripts + +### On Local Machine + +#### Setting up test environment + +```sh + +# create and activate a virtualenv using your preferred method. Example: +python -m venv venv +source venv/bin/activate + + +# install requirements +pip install -r .\MobileTest\ccc_bulk_submission\requires.txt + +``` + +[More on setting up the machine and the scripts](https://docs.google.com/document/d/12C-BJzdDCu0tl3WfwnP90jdzT4SGEMz--p10FrYSJ8Y/edit) + + +#### Running Tests + +- Run tests using pytest command like: + +```sh + +# To execute all the test cases +python .\MobileTest\ccc_bulk_submission\main.py + +``` + + +### Trigger Manually on Gitaction + +clone this repository + +To manually trigger the script, + - Go to [Gitactions](https://github.com/dimagi/dimagi-qa/actions/) + - Select the desired workflow, here [HQ Smoke Tests action](https://github.com/dimagi/dimagi-qa/actions/workflows/hq-smoke-tests.yml) + - Run workflow + - Select workflow as ```master``` + - Select the environment as desired + - Run! + +If you are a part of the QA team, you'll receive emails for the result of the run after it's complete. + +clone this repository + +Besides, you should be able to find the zipped results in the **Artifacts** section, of the corresponding run (after it's complete). diff --git a/MobileTest/QA_7315/__init__.py b/MobileTest/QA_7315/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/MobileTest/QA_7315/commcare_2.53.1.apk b/MobileTest/QA_7315/commcare_2.53.1.apk new file mode 100644 index 000000000..f7ff4852c Binary files /dev/null and b/MobileTest/QA_7315/commcare_2.53.1.apk differ diff --git a/MobileTest/QA_7315/commcare_2.54.1.apk b/MobileTest/QA_7315/commcare_2.54.1.apk new file mode 100644 index 000000000..1e918ba3b Binary files /dev/null and b/MobileTest/QA_7315/commcare_2.54.1.apk differ diff --git a/MobileTest/QA_7315/report.html b/MobileTest/QA_7315/report.html new file mode 100644 index 000000000..9a77c1f1e --- /dev/null +++ b/MobileTest/QA_7315/report.html @@ -0,0 +1,1091 @@ + + + + + report.html + + + + +

report.html

+

Report generated on 11-Dec-2024 at 14:54:57 by pytest-html + v4.1.1

+
+

Environment

+
+
+ + + + + +
+
+

Summary

+
+
+

1 test took 00:06:32.

+

(Un)check the boxes to filter the results.

+
+ +
+
+
+
+ + 1 Failed, + + 0 Passed, + + 0 Skipped, + + 0 Expected failures, + + 0 Unexpected passes, + + 1 Errors, + + 0 Reruns +
+
+  /  +
+
+
+
+
+
+
+
+ + + + + + + + + +
ResultTestDurationLinks
+ + + \ No newline at end of file diff --git a/MobileTest/QA_7315/requires.txt b/MobileTest/QA_7315/requires.txt new file mode 100644 index 000000000..a512b12bd --- /dev/null +++ b/MobileTest/QA_7315/requires.txt @@ -0,0 +1,3 @@ +Appium-Python-Client >= 4.0.0 +selenium == 4.20.0 +pytest \ No newline at end of file diff --git a/MobileTest/QA_7315/test_new_apk.py b/MobileTest/QA_7315/test_new_apk.py new file mode 100644 index 000000000..09f3211e6 --- /dev/null +++ b/MobileTest/QA_7315/test_new_apk.py @@ -0,0 +1,198 @@ +# import os +import random +import string +import time +import unittest +from appium import webdriver +from appium.options.android import UiAutomator2Options +from appium.webdriver.common.appiumby import AppiumBy +from selenium.common import NoSuchElementException, TimeoutException +from selenium.webdriver.support import expected_conditions as ec +from selenium.webdriver.support.wait import WebDriverWait + +app_path = 'C:\\Users\\dsi-user\\PycharmProjects\\Anroid\\apps\\commcare_2.54.1.apk' +capabilities = UiAutomator2Options().load_capabilities({ + "platformName": "Android", + "udid": "emulator-5554", + "automationName": "UIAutomator2", + "deviceName": "Pixel_8_New_APK", + "avd": "Pixel_8_New_APK", + "appWaitPackage": "org.commcare.dalvik", + # "appActivity": "org.commcare.activities.CommCareSetupActivity", + "appWaitActivity": "org.commcare.activities.LoginActivity", + # "appWaitActivity": "org.commcare.activities.DispatchActivity", + "autoGrantPermissions": "true", + "app": app_path, + "noReset": "true", + "fullReset": "false", + "dontStopAppOnReset": "false" + } + ) + +appium_server_url = 'http://localhost:4723/wd/hub' +chars = string.ascii_lowercase + string.digits +random_string = ''.join(random.choices(chars, k=6)) +random_number = random.randint(100, 19999) + + +class TestAppium(unittest.TestCase): + def setUp(self) -> None: + self.driver = webdriver.Remote(appium_server_url, + options=capabilities + ) + + self.case_list_name = 'Case List' + self.form_name = 'Registration Form' + self.enter_code = "//android.widget.TextView[@text='Enter Code']" + self.profile_code = "org.commcare.dalvik:id/edit_profile_location" + self.start_install = "org.commcare.dalvik:id/start_install" + self.install = "//android.widget.TextView[@text='Start Install']" + self.username = "org.commcare.dalvik:id/edit_username" + self.password = "org.commcare.dalvik:id/edit_password" + self.login = "org.commcare.dalvik:id/login_button" + self.start_button = "//android.widget.TextView[@text='Start']" + self.sync_button = "//android.widget.TextView[@text='Sync with Server']" + self.case_list = "//android.widget.TextView[@text='Case List']" + self.form = "//android.widget.TextView[@text='Registration Form']" + self.text_field = "//android.widget.EditText" + self.radio_btn_field = "//*[@text='pune']" + self.submit_button = "//android.widget.TextView[@text='FINISH']" + self.next_btn = "org.commcare.dalvik:id/nav_btn_next" + + # self.go_to_menu = (AppiumBy.ID, "org.commcare.dalvik:id/connect_login_button") + # self.password_field = (AppiumBy.ID, "org.commcare.dalvik:id/connect_password_verify_input") + # self.password_verify_btn = (AppiumBy.ID, "org.commcare.dalvik:id/connect_password_verify_button") + # self.my_jobs = (AppiumBy.ANDROID_UIAUTOMATOR, "new UiSelector().text(\"MY JOBS\")") + # # self.payment_verification_job = (AppiumBy.XPATH, "//android.widget.TextView[@text=\"Payment Verifications\"]//following-sibling::android.widget.ImageView[@resource-id=\"org.commcare.dalvik:id/button\"]\n") + # # self.verification_pay_tab = + # self.launch_app =(AppiumBy.ID,"org.commcare.dalvik:id/connect_progress_button") + # self.start_btn = (AppiumBy.XPATH,"//android.widget.TextView[@text='Start']") + # self.case_list = (AppiumBy.XPATH, "//android.widget.TextView[@text='Case List']") + # self.reg_form = (AppiumBy.XPATH, "//android.widget.TextView[@text='Registration Form']") + # self.text_input = (AppiumBy.XPATH, "//android.widget.EditText") + # self.number_input = (AppiumBy.XPATH, "//android.widget.EditText") + # + # self.finish_btn = (AppiumBy.XPATH, "//android.widget.TextView[@text='FINISH']") + # self.back_btn = (AppiumBy.XPATH, "//android.widget.ImageButton[@content-desc='Navigate up']") + # self.sync_btn = (AppiumBy.XPATH, "//android.widget.TextView[@text='Sync with Server']") + self.log_out = "//android.widget.TextView[@text='Log out of CommCare']" + # self.warning = (AppiumBy.ID, "org.commcare.dalvik:id/connect_progress_delivery_warning_text") + + def tearDown(self) -> None: + if self.driver: + self.driver.quit() + + def click_xpath(self, locator): + element = self.driver.find_element(AppiumBy.XPATH, locator) + element.click() + + def click_id(self, locator): + element = self.driver.find_element(AppiumBy.ID, locator) + element.click() + + def send_text_xpath(self, locator, user_input): + element = self.driver.find_element(AppiumBy.XPATH, locator) + element.send_keys(user_input) + + def send_text_id(self, locator, user_input): + element = self.driver.find_element(AppiumBy.ID, locator) + element.send_keys(user_input) + + def click(self, locator): + time.sleep(2) + clickable = ec.visibility_of_element_located(locator) + element = WebDriverWait(self.driver, 30, poll_frequency=1).until(clickable, + message="Couldn't find locator: " + str( + locator + ) + ) + element.click() + + def send_text(self, locator, value): + time.sleep(2) + clickable = ec.visibility_of_element_located(locator) + element = WebDriverWait(self.driver, 30, poll_frequency=1).until(clickable, + message="Couldn't find locator: " + str( + locator + ) + ) + element.send_keys(value) + + # def send_text_xpath(self, locator, user_input): + # element = self.driver.find_element(AppiumBy.XPATH, locator) + # element.send_keys(user_input) + # + # def send_text_id(self, locator, user_input): + # element = self.driver.find_element(AppiumBy.ID, locator) + # element.send_keys(user_input) + + def wait_for_element(self, locator, timeout=20): + clickable = ec.element_to_be_clickable(locator) + WebDriverWait(self.driver, timeout, poll_frequency=5).until(clickable, + message="Couldn't find locator: " + str(locator) + ) + + def is_enabled(self, locator): + try: + element = self.driver.find_element(*locator) + is_enabled = element.is_enabled() + except TimeoutException: + is_enabled = False + return bool(is_enabled) + # + # def is_displayed(self, locator): + # try: + # element = self.driver.find_element(*locator) + # is_displayed = element.is_displayed() + # except (TimeoutException, NoSuchElementException): + # is_displayed = False + # return bool(is_displayed) + + # def is_present(self, locator): + # try: + # element = self.driver.find_element(*locator) + # is_displayed = True + # except NoSuchElementException: + # is_displayed = False + # return bool(is_displayed) + + def test_form_submission(self) -> None: + # time.sleep(10) + # self.driver.find_element(AppiumBy.XPATH, self.enter_code).click() + # time.sleep(10) + # self.driver.find_element(AppiumBy.ID, self.profile_code).send_keys('4gjhlPe') + # time.sleep(5) + # self.driver.find_element(AppiumBy.ID, self.start_install).click() + # time.sleep(3) + # self.driver.find_element(AppiumBy.XPATH, self.install).click() + time.sleep(25) + self.driver.find_element(AppiumBy.ID, self.username).send_keys('kdd') + self.driver.find_element(AppiumBy.ID, self.password).send_keys('123') + self.driver.find_element(AppiumBy.ID, self.login).click() + time.sleep(30) + self.driver.find_element(AppiumBy.XPATH, self.start_button).click() + time.sleep(10) + self.driver.find_element(AppiumBy.XPATH, self.case_list).click() + time.sleep(10) + self.driver.find_element(AppiumBy.XPATH, self.form).click() + time.sleep(10) + self.driver.find_element(AppiumBy.XPATH, self.text_field).send_keys(random_string) + print(random_string) + self.driver.find_element(AppiumBy.ID, self.next_btn).click() + time.sleep(3) + self.driver.find_element(AppiumBy.XPATH, self.radio_btn_field).click() + time.sleep(3) + self.driver.find_element(AppiumBy.ID, self.next_btn).click() + time.sleep(3) + self.driver.find_element(AppiumBy.XPATH, self.text_field).send_keys('23') + self.driver.find_element(AppiumBy.XPATH, self.submit_button).click() + time.sleep(2) + # assert self.driver.find_element(AppiumBy.XPATH, "//android.widget.TextView[@text='1 form sent to server!']" + # ).is_displayed() + self.driver.find_element(AppiumBy.XPATH, self.sync_button).click() + time.sleep(120) + self.driver.find_element(AppiumBy.XPATH, self.log_out).click() + + +if __name__ == '__main__': + unittest.main() diff --git a/MobileTest/QA_7315/test_old_apk.py b/MobileTest/QA_7315/test_old_apk.py new file mode 100644 index 000000000..81e32fa33 --- /dev/null +++ b/MobileTest/QA_7315/test_old_apk.py @@ -0,0 +1,205 @@ +import os +import random +import string +import time +import unittest +from appium import webdriver +from appium.options.android import UiAutomator2Options +from appium.webdriver.common.appiumby import AppiumBy +from selenium.common import NoSuchElementException, TimeoutException +from selenium.webdriver.support import expected_conditions as ec +from selenium.webdriver.support.wait import WebDriverWait + +app_path = 'C:\\Users\\dsi-user\\PycharmProjects\\Anroid\\apps\\commcare_2.53.1.apk' +capabilities = UiAutomator2Options().load_capabilities({ + "platformName": "Android", + "udid": "emulator-5556", + "automationName": "UIAutomator2", + "deviceName": "Pixel_8_Old_APK", + "avd": "Pixel_8_Old_APK", + "appWaitPackage": "org.commcare.dalvik", + "appActivity": "org.commcare.activities.CommCareSetupActivity", + # "appWaitActivity": "org.commcare.activities.LoginActivity", + # "appWaitActivity": "org.commcare.activities.DispatchActivity", + "autoGrantPermissions": "true", + "app": app_path, + "noReset": "true", + "fullReset": "false", + "dontStopAppOnReset": "false" + } + ) + +appium_server_url = 'http://localhost:4723/wd/hub' +chars = string.ascii_lowercase + string.digits +random_string = ''.join(random.choices(chars, k=6)) +random_number = random.randint(100, 19999) + + +class TestAppium(unittest.TestCase): + def setUp(self) -> None: + self.driver = webdriver.Remote(appium_server_url, + options=capabilities + ) + + self.case_list_name = 'Case List' + self.form_name = 'Registration Form' + self.enter_code = "//android.widget.TextView[@text='Enter Code']" + self.profile_code = "org.commcare.dalvik:id/edit_profile_location" + self.start_install = "org.commcare.dalvik:id/start_install" + self.install = "//android.widget.TextView[@text='Start Install']" + self.username = "org.commcare.dalvik:id/edit_username" + self.password = "org.commcare.dalvik:id/edit_password" + self.login = "org.commcare.dalvik:id/login_button" + self.start_button = "//android.widget.TextView[@text='Start']" + self.sync_button = "//android.widget.TextView[@text='Sync with Server']" + self.case_list = "//android.widget.TextView[@text='Case List']" + self.form = "//android.widget.TextView[@text='Registration Form']" + self.text_field = "//android.widget.EditText" + self.radio_btn_field = "//*[@text='mumbai']" + self.submit_button = "//android.widget.TextView[@text='FINISH']" + self.next_btn = "org.commcare.dalvik:id/nav_btn_next" + + self.go_to_menu = (AppiumBy.ID, "org.commcare.dalvik:id/connect_login_button") + self.password_field = (AppiumBy.ID, "org.commcare.dalvik:id/connect_password_verify_input") + self.password_verify_btn = (AppiumBy.ID, "org.commcare.dalvik:id/connect_password_verify_button") + self.my_jobs = (AppiumBy.ANDROID_UIAUTOMATOR, "new UiSelector().text(\"MY JOBS\")") + self.payment_verification_job = (AppiumBy.XPATH, + "//android.widget.TextView[@text=\"Payment Verifications\"]//following-sibling::android.widget.ImageView[@resource-id=\"org.commcare.dalvik:id/button\"]\n") + + # self.launch_app = (AppiumBy.ID, "org.commcare.dalvik:id/connect_progress_button") + # self.start_btn = (AppiumBy.XPATH, "//android.widget.TextView[@text='Start']") + # self.case_list = (AppiumBy.XPATH, "//android.widget.TextView[@text='Case List']") + # self.reg_form = (AppiumBy.XPATH, "//android.widget.TextView[@text='Registration Form']") + # self.text_input = (AppiumBy.XPATH, "//android.widget.EditText") + # self.number_input = (AppiumBy.XPATH, "//android.widget.EditText") + # + # self.finish_btn = (AppiumBy.XPATH, "//android.widget.TextView[@text='FINISH']") + # self.back_btn = (AppiumBy.XPATH, "//android.widget.ImageButton[@content-desc='Navigate up']") + # self.sync_btn = (AppiumBy.XPATH, "//android.widget.TextView[@text='Sync with Server']") + self.log_out = "//android.widget.TextView[@text='Log out of CommCare']" + # self.warning = (AppiumBy.ID, "org.commcare.dalvik:id/connect_progress_delivery_warning_text") + + def tearDown(self) -> None: + if self.driver: + self.driver.quit() + + def click_xpath(self, locator): + element = self.driver.find_element(AppiumBy.XPATH, locator) + element.click() + + def click_id(self, locator): + element = self.driver.find_element(AppiumBy.ID, locator) + element.click() + + def send_text_xpath(self, locator, user_input): + element = self.driver.find_element(AppiumBy.XPATH, locator) + element.send_keys(user_input) + + def send_text_id(self, locator, user_input): + element = self.driver.find_element(AppiumBy.ID, locator) + element.send_keys(user_input) + + def click(self, locator): + time.sleep(2) + clickable = ec.visibility_of_element_located(locator) + element = WebDriverWait(self.driver, 30, poll_frequency=1).until(clickable, + message="Couldn't find locator: " + str( + locator + ) + ) + element.click() + + def send_text(self, locator, value): + time.sleep(2) + clickable = ec.visibility_of_element_located(locator) + element = WebDriverWait(self.driver, 30, poll_frequency=1).until(clickable, + message="Couldn't find locator: " + str( + locator + ) + ) + element.send_keys(value) + + # def send_text_xpath(self, locator, user_input): + # element = self.driver.find_element(AppiumBy.XPATH, locator) + # element.send_keys(user_input) + # + # def send_text_id(self, locator, user_input): + # element = self.driver.find_element(AppiumBy.ID, locator) + # element.send_keys(user_input) + + def wait_for_element(self, locator, timeout=20): + clickable = ec.element_to_be_clickable(locator) + WebDriverWait(self.driver, timeout, poll_frequency=5).until(clickable, + message="Couldn't find locator: " + str(locator) + ) + + def fetch_random_string(self): + return random_string + + def fetch_random_digit(self): + return str(random_number) + + def is_enabled(self, locator): + try: + element = self.driver.find_element(*locator) + is_enabled = element.is_enabled() + except TimeoutException: + is_enabled = False + return bool(is_enabled) + + def is_displayed(self, locator): + try: + element = self.driver.find_element(*locator) + is_displayed = element.is_displayed() + except (TimeoutException, NoSuchElementException): + is_displayed = False + return bool(is_displayed) + + def is_present(self, locator): + try: + element = self.driver.find_element(*locator) + is_displayed = True + except NoSuchElementException: + is_displayed = False + return bool(is_displayed) + + def test_form_submission(self) -> None: + time.sleep(10) + self.driver.find_element(AppiumBy.XPATH, self.enter_code).click() + time.sleep(10) + self.driver.find_element(AppiumBy.ID, self.profile_code).send_keys('4gjhlPe') + time.sleep(5) + self.driver.find_element(AppiumBy.ID, self.start_install).click() + time.sleep(3) + self.driver.find_element(AppiumBy.XPATH, self.install).click() + time.sleep(25) + self.driver.find_element(AppiumBy.ID, self.username).send_keys('04') + self.driver.find_element(AppiumBy.ID, self.password).send_keys('123') + self.driver.find_element(AppiumBy.ID, self.login).click() + time.sleep(70) + self.driver.find_element(AppiumBy.XPATH, self.start_button).click() + time.sleep(10) + self.driver.find_element(AppiumBy.XPATH, self.case_list).click() + time.sleep(3) + self.driver.find_element(AppiumBy.XPATH, self.form).click() + time.sleep(3) + self.driver.find_element(AppiumBy.XPATH, self.text_field).send_keys(random_string) + print(random_string) + self.driver.find_element(AppiumBy.ID, self.next_btn).click() + time.sleep(3) + self.driver.find_element(AppiumBy.XPATH, self.radio_btn_field).click() + time.sleep(3) + self.driver.find_element(AppiumBy.ID, self.next_btn).click() + time.sleep(3) + self.driver.find_element(AppiumBy.XPATH, self.text_field).send_keys('23') + self.driver.find_element(AppiumBy.XPATH, self.submit_button).click() + time.sleep(2) + # assert self.driver.find_element(AppiumBy.XPATH, "//android.widget.TextView[@text='1 form sent to server!']" + # ).is_displayed() + self.driver.find_element(AppiumBy.XPATH, self.sync_button).click() + time.sleep(120) + self.driver.find_element(AppiumBy.XPATH, self.log_out).click() + + +if __name__ == '__main__': + unittest.main() diff --git a/P1P2Tests/testCases/test_02_users.py b/P1P2Tests/testCases/test_02_users.py index d3ad22238..6329fbc02 100644 --- a/P1P2Tests/testCases/test_02_users.py +++ b/P1P2Tests/testCases/test_02_users.py @@ -3,6 +3,8 @@ import pytest +from HQSmokeTests.testPages.android.android_screen import AndroidScreen +from HQSmokeTests.testPages.applications.application_page import ApplicationPage from HQSmokeTests.testPages.users.group_page import GroupPage from HQSmokeTests.userInputs.user_inputs import UserData from common_utilities.generate_random_string import fetch_random_string @@ -16,6 +18,21 @@ group_id["user_new"] = "username_"+fetch_random_string()+"_new" + +@pytest.mark.user +@pytest.mark.mobileWorker +@pytest.mark.mobileWorker +@pytest.mark.p1p2EscapeDefect +def test_case_89_verify_user_location_alert(driver, settings): + mw = MobileWorkerPage(driver) + menu = HomePage(driver, settings) + menu.users_menu() + mw.mobile_worker_menu() + mw.select_mobile_worker_created(UserData.app_login) + mw.select_location() + mw.remove_location() + mw.verify_location_alert_not_present() + @pytest.mark.user @pytest.mark.mobileWorker @pytest.mark.user_profiles @@ -90,3 +107,30 @@ def test_aftertest_cleanup_items_in_users_menu(driver, settings): clean2.click_group_menu() clean2.delete_test_groups() print("Deleted the group") + + +@pytest.mark.application +@pytest.mark.appSettings +@pytest.mark.p1p2EscapeDefect +def test_case_91_login_with_new_password(driver, settings): + menu = HomePage(driver, settings) + menu.applications_menu(UserData.village_application) + load = ApplicationPage(driver) + code = load.get_app_code(UserData.village_application) + username = "username_" + fetch_random_string() + worker = MobileWorkerPage(driver) + menu = HomePage(driver, settings) + menu.users_menu() + worker.delete_bulk_users() + worker.mobile_worker_menu() + worker.create_mobile_worker() + worker.mobile_worker_enter_username(username) + worker.mobile_worker_enter_password(fetch_random_string()) + worker.click_create(username) + mobile = AndroidScreen(settings) + mobile.verify_login_with_old_password(code, username, fetch_random_string()) + worker.mobile_worker_menu() + worker.select_mobile_worker_created(username) + worker.reset_mobile_worker_password("new_"+fetch_random_string()) + mobile.verify_login_with_new_password(username, "new_"+fetch_random_string()) + mobile.close_android_driver() diff --git a/P1P2Tests/testCases/test_03_exports.py b/P1P2Tests/testCases/test_03_exports.py new file mode 100644 index 000000000..b8808300a --- /dev/null +++ b/P1P2Tests/testCases/test_03_exports.py @@ -0,0 +1,49 @@ +import pytest + +from HQSmokeTests.testPages.data.export_data_page import ExportDataPage +from HQSmokeTests.testPages.home.home_page import HomePage +from P1P2Tests.userInputs.user_inputs import UserData + +""""Contains test cases related to the Exports module""" + +@pytest.mark.data +@pytest.mark.exportsFormData +@pytest.mark.p1p2EscapeDefect +def test_case_21_form_exports(driver, settings): + home = HomePage(driver, settings) + home.data_menu() + export = ExportDataPage(driver) + name = export.add_form_exports() + export.form_exports(name) + +@pytest.mark.data +@pytest.mark.exportsCaseData +@pytest.mark.p1p2EscapeDefect +def test_case_21_case_exports(driver, settings): + home = HomePage(driver, settings) + home.data_menu() + export = ExportDataPage(driver) + name = export.add_case_exports() + export.case_exports(name) + + +@pytest.mark.data +@pytest.mark.exportsFormData +@pytest.mark.p1p2EscapeDefect +def test_case_88_repeat_form_exports(driver, settings): + home = HomePage(driver, settings) + home.data_menu() + export = ExportDataPage(driver) + export.add_repeat_form_exports(UserData.basic_test_app[0], UserData.basic_test_app[1], UserData.basic_test_app[2], UserData.repeat_form_export_name) + + + +@pytest.mark.data +@pytest.mark.deleteBulkExports +def test_exports_cleanup(driver, settings): + home = HomePage(driver, settings) + home.data_menu() + export = ExportDataPage(driver) + export.delete_all_bulk_exports() + + diff --git a/P1P2Tests/testCases/test_04_integration_exports.py b/P1P2Tests/testCases/test_04_integration_exports.py index 3d8e9172f..a7852be0a 100644 --- a/P1P2Tests/testCases/test_04_integration_exports.py +++ b/P1P2Tests/testCases/test_04_integration_exports.py @@ -31,3 +31,14 @@ def test_case_26_excel_dashboard_integration_case(driver, settings): link = export.check_feed_link(case) export.verify_duplicate_data_in_dashboard(link, settings['login_username'], settings['login_password']) +@pytest.mark.data +@pytest.mark.powerBiTableauIntegrationCase +@pytest.mark.p1p2EscapeDefect +#SAAS-13243, SAAS-14468 +def test_case_27_powerbi_tableau_integration_case(driver, settings): + username = settings["login_username"] + password = settings["login_password"] + home = HomePage(driver, settings) + home.data_menu() + export = ExportDataPage(driver) + export.power_bi_tableau_integration_case(username, password) \ No newline at end of file diff --git a/P1P2Tests/testCases/test_05_roles.py b/P1P2Tests/testCases/test_05_roles.py index 6bb4f727e..b2f2f2755 100644 --- a/P1P2Tests/testCases/test_05_roles.py +++ b/P1P2Tests/testCases/test_05_roles.py @@ -2,6 +2,7 @@ import pytest +from HQSmokeTests.testPages.data.export_data_page import ExportDataPage from HQSmokeTests.testPages.home.home_page import HomePage from HQSmokeTests.testPages.reports.report_page import ReportPage from HQSmokeTests.testPages.users.mobile_workers_page import MobileWorkerPage @@ -49,6 +50,7 @@ def test_case_73_non_admin_role_permission(driver, settings): menu.users_menu() webuser.edit_user_permission("Admin") + @pytest.mark.user @pytest.mark.mobileWorker @pytest.mark.groups @@ -61,7 +63,7 @@ def test_case_74_delete_role_column(driver, settings): login.logout() time.sleep(10) login.login(settings["login_username"], settings["login_password"]) - username = "username_p1p2_"+fetch_random_string() + username = "username_p1p2_" + fetch_random_string() user = MobileWorkerPage(driver) home = HomePage(driver, settings) home.users_menu() @@ -93,6 +95,56 @@ def test_case_74_delete_role_column(driver, settings): role.delete_test_roles() +@pytest.mark.user +@pytest.mark.role +@pytest.mark.userExport +@pytest.mark.p1p2EscapeDefect +def test_case_94_roles_and_exports(driver, settings): + login = LoginPage(driver, settings["url"]) + webuser = WebUsersPage(driver) + menu = HomePage(driver, settings) + menu.users_menu() + webuser.change_user_role(UserData.p1p2_user, 'Admin') + role = RolesPermissionPage(driver, settings) + menu.users_menu() + role.roles_menu_click() + role.delete_test_roles() + role.roles_menu_click() + role.add_shared_export_role(role.role_no_shared_export_created, "NO") + role.roles_menu_click() + role.add_shared_export_role(role.role_yes_shared_export_created, "YES") + menu.data_menu() + export = ExportDataPage(driver) + export.delete_bulk_exports() + export.add_shared_form_exports(UserData.private_export_no, 'NO') + menu.data_menu() + export.add_shared_form_exports(UserData.private_export_yes, 'YES') + menu.users_menu() + webuser.change_user_role(UserData.p1p2_user, role.role_no_shared_export_created) + login.logout() + time.sleep(10) + login.login(UserData.p1p2_user, settings["login_password"]) + menu.data_menu() + export.verify_shared_export_section(UserData.private_export_no, UserData.private_export_yes, 'NO') + login.logout() + time.sleep(10) + login.login(settings["login_username"], settings["login_password"]) + menu.users_menu() + webuser.change_user_role(UserData.p1p2_user, role.role_yes_shared_export_created) + login.logout() + time.sleep(10) + login.login(UserData.p1p2_user, settings["login_password"]) + menu.data_menu() + export.verify_shared_export_section(UserData.private_export_no, UserData.private_export_yes, 'YES') + login.logout() + time.sleep(10) + login.login(settings["login_username"], settings["login_password"]) + menu.data_menu() + export.delete_all_bulk_exports() + menu.users_menu() + webuser.change_user_role(UserData.p1p2_user, 'Admin') + + @pytest.mark.user @pytest.mark.role def test_cleanup_items_in_role_menu(driver, settings): diff --git a/P1P2Tests/testCases/test_06_data.py b/P1P2Tests/testCases/test_06_data.py new file mode 100644 index 000000000..447d070bc --- /dev/null +++ b/P1P2Tests/testCases/test_06_data.py @@ -0,0 +1,34 @@ +import pytest + +from HQSmokeTests.testPages.data.copy_cases_page import CopyCasesPage +from HQSmokeTests.testPages.data.data_dictionary_page import DataDictionaryPage +from HQSmokeTests.testPages.data.deduplicate_case_page import DeduplicateCasePage +from HQSmokeTests.testPages.data.manage_forms_page import ManageFormsPage +from HQSmokeTests.testPages.data.import_cases_page import ImportCasesPage +from HQSmokeTests.testPages.data.reassign_cases_page import ReassignCasesPage +from HQSmokeTests.testPages.data.auto_case_update_page import AutoCaseUpdatePage +from HQSmokeTests.testPages.data.lookup_table_page import LookUpTablePage +from HQSmokeTests.testPages.home.home_page import HomePage + +""""Contains test cases related to the Data module""" + + +@pytest.mark.data +@pytest.mark.reassignCases +@pytest.mark.p1p2EscapeDefect +def test_case_30_reassign_cases(driver, settings): + home = HomePage(driver, settings) + home.data_menu() + reassign = ReassignCasesPage(driver, settings) + reassign.get_cases(settings['login_username']) + reassign.reassign_case() + +@pytest.mark.data +@pytest.mark.copyCases +@pytest.mark.p1p2EscapeDefect +def test_case_60_copy_cases(driver, settings): + home = HomePage(driver, settings) + home.data_menu() + copy = CopyCasesPage(driver, settings) + copy.get_cases(settings['login_username']) + copy.copy_case() diff --git a/P1P2Tests/testCases/test_07_applications.py b/P1P2Tests/testCases/test_07_applications.py new file mode 100644 index 000000000..06be1c7e7 --- /dev/null +++ b/P1P2Tests/testCases/test_07_applications.py @@ -0,0 +1,45 @@ +import pytest + +from HQSmokeTests.testPages.applications.app_preview import AppPreviewPage +from HQSmokeTests.testPages.applications.application_page import ApplicationPage +from HQSmokeTests.testPages.android.android_screen import AndroidScreen +from HQSmokeTests.testPages.home.home_page import HomePage +from HQSmokeTests.testPages.reports.report_page import ReportPage +from P1P2Tests.userInputs.user_inputs import UserData + +""""Contains test cases related to the Application module""" + +@pytest.mark.application +@pytest.mark.appSettings +@pytest.mark.p1p2EscapeDefect +def test_case_84_verify_form_settings(driver, settings): + menu = HomePage(driver, settings) + menu.applications_menu(UserData.reassign_cases_application) + load = ApplicationPage(driver) + load.verify_form_settings_page(UserData.form_name) + load.verify_form_settings_page(UserData.followup_form_name) + +@pytest.mark.application +@pytest.mark.appSettings +@pytest.mark.p1p2EscapeDefect +def test_case_85_verify_app_version_page(driver, settings): + menu = HomePage(driver, settings) + menu.applications_menu(UserData.reassign_cases_application) + load = ApplicationPage(driver) + load.verify_app_version_page() + +@pytest.mark.application +@pytest.mark.appSettings +@pytest.mark.p1p2EscapeDefect +def test_case_90_verify_app_installation(driver, settings): + menu = HomePage(driver, settings) + menu.applications_menu(UserData.village_application) + load = ApplicationPage(driver) + code = load.get_app_code(UserData.village_application) + mobile = AndroidScreen(settings) + mobile.verify_app_install(code) + mobile.close_android_driver() + + + + diff --git a/P1P2Tests/testCases/test_08_reports.py b/P1P2Tests/testCases/test_08_reports.py index 4ac08166e..d448e9901 100644 --- a/P1P2Tests/testCases/test_08_reports.py +++ b/P1P2Tests/testCases/test_08_reports.py @@ -3,6 +3,7 @@ from HQSmokeTests.testPages.home.home_page import HomePage from HQSmokeTests.testPages.reports.report_page import ReportPage from HQSmokeTests.testPages.webapps.web_apps_page import WebAppsPage +from P1P2Tests.userInputs.user_inputs import UserData """"Contains test cases related to the Data module""" @@ -22,3 +23,56 @@ def test_case_17_create_form_report(driver, settings): load.configure_add_report() load.delete_report() +@pytest.mark.reportBuilderForm +@pytest.mark.reportBuilderCase +@pytest.mark.editReport +@pytest.mark.p1p2EscapeDefect +def test_case_17_create_case_report(driver, settings): + report = HomePage(driver, settings) + driver.refresh() + report.reports_menu() + load = ReportPage(driver) + load.create_report_builder_case_report() + load.delete_report() + +@pytest.mark.report +@pytest.mark.caseListPage +@pytest.mark.p1p2EscapeDefect +def test_case_82_check_case_list(driver, settings): + home = HomePage(driver, settings) + home.reports_menu() + report = ReportPage(driver) + report.verify_case_list_page() + +@pytest.mark.report +@pytest.mark.caseListPage +@pytest.mark.p1p2EscapeDefect +def test_case_86_export_to_excel_config_report(driver, settings): + home = HomePage(driver, settings) + home.reports_menu() + report = ReportPage(driver) + report.export_to_excel_config_report(UserData.report_for_p1p2) + +@pytest.mark.report +@pytest.mark.applicationStatusPage +@pytest.mark.p1p2EscapeDefect +def test_case_87_application_status_report(driver, settings): + home = HomePage(driver, settings) + home.reports_menu() + report = ReportPage(driver) + report.application_status_report_search() + report.verify_sorted_list() + + +@pytest.mark.report +@pytest.mark.caseListExplorer +@pytest.mark.p1p2EscapeDefect +def test_case_92_verify_case_list_explorer_properties(driver, settings): + home = HomePage(driver, settings) + home.reports_menu() + report = ReportPage(driver) + name = report.verify_case_list_explorer_properties() + report.add_new_property(name) + + + diff --git a/P1P2Tests/testCases/test_09_messaging.py b/P1P2Tests/testCases/test_09_messaging.py new file mode 100644 index 000000000..02d8c2c58 --- /dev/null +++ b/P1P2Tests/testCases/test_09_messaging.py @@ -0,0 +1,46 @@ +import pytest + +from HQSmokeTests.testPages.home.home_page import HomePage +from HQSmokeTests.testPages.messaging.messaging_page import MessagingPage +from HQSmokeTests.testPages.reports.report_page import ReportPage + +""""Contains test cases related to the Messaging module""" + + + +@pytest.mark.messaging +@pytest.mark.broadcasts +@pytest.mark.p1p2EscapeDefect +def test_case_43_broadcast(driver, settings): + menu = HomePage(driver, settings) + msg = MessagingPage(driver) + menu.messaging_menu() + msg.send_broadcast_message() + + +@pytest.mark.messaging +@pytest.mark.conditionalAlerts +@pytest.mark.report +@pytest.mark.reportMessaging +@pytest.mark.p1p2EscapeDefect +def test_case_44_create_cond_alert(driver, settings): + menu = HomePage(driver, settings) + msg = MessagingPage(driver) + menu.messaging_menu() + cond_alert = msg.create_cond_alert() + menu.reports_menu() + history = ReportPage(driver) + history.validate_messaging_history_for_cond_alert(cond_alert) + menu.messaging_menu() + msg.remove_cond_alert() + + +@pytest.mark.projectSettings +@pytest.mark.currentSubscription +@pytest.mark.p1p2EscapeDefect +def test_case_52_settings_pages(driver, settings): + msg = MessagingPage(driver) + home = HomePage(driver, settings) + home.project_settings_page() + msg.current_subscription_page() + diff --git a/P1P2Tests/testCases/test_10_p1_p2_defects.py b/P1P2Tests/testCases/test_10_p1_p2_defects.py index 08253688b..49bedc651 100644 --- a/P1P2Tests/testCases/test_10_p1_p2_defects.py +++ b/P1P2Tests/testCases/test_10_p1_p2_defects.py @@ -1,13 +1,16 @@ import pytest +from HQSmokeTests.testPages.android.android_screen import AndroidScreen from HQSmokeTests.testPages.applications.app_preview import AppPreviewPage from HQSmokeTests.testPages.applications.application_page import ApplicationPage from HQSmokeTests.testPages.data.export_data_page import ExportDataPage from HQSmokeTests.testPages.data.import_cases_page import ImportCasesPage from HQSmokeTests.testPages.email.email_verification import EmailVerification from HQSmokeTests.testPages.home.home_page import HomePage +from HQSmokeTests.testPages.messaging.messaging_page import MessagingPage from HQSmokeTests.testPages.project_settings.repeaters_page import RepeatersPage from HQSmokeTests.testPages.reports.report_page import ReportPage +from HQSmokeTests.testPages.webapps.web_apps_page import WebAppsPage from HQSmokeTests.userInputs.user_inputs import UserData @@ -129,4 +132,45 @@ def test_case_81_parent_child_case_imports(driver, settings): home.data_menu() export.verify_case_import(assignment) +@pytest.mark.projectSettings +@pytest.mark.createRepeater +@pytest.mark.editRepeater +@pytest.mark.p1p2EscapeDefect +def test_case_83_data_forwarding_add_edit(driver, settings): + home = HomePage(driver, settings) + home.project_settings_page() + repeater = RepeatersPage(driver) + repeater.delete_all_repeaters() + repeater.add_repeater() + repeater.edit_repeater() + repeater.delete_repeater() + +@pytest.mark.data +@pytest.mark.p1p2EscapeDefect +def test_case_93_cond_alert_on_form_submit(driver, settings): + menu = HomePage(driver, settings) + msg = MessagingPage(driver) + menu.messaging_menu() + msg.remove_all_cond_alert() + menu.messaging_menu() + cond_alert, subject = msg.create_cond_alert_for_doesnot_have_value() + menu.web_apps_menu() + webapps = WebAppsPage(driver) + webapps.verify_apps_presence() + case_name = webapps.submit_case_change_register_form_no_value() + menu = HomePage(driver, settings) + menu.applications_menu(UserData.reassign_cases_application) + load = ApplicationPage(driver) + code = load.get_app_code(UserData.reassign_cases_application) + mobile = AndroidScreen(settings) + mobile.verify_app_install(code) + mobile.close_android_driver() + menu.reports_menu() + report = ReportPage(driver) + case_id = report.get_case_id_from_case_list_explorer(case_name) + export = ExportDataPage(driver) + menu.data_menu() + export.check_for_case_id(case_id) + email = EmailVerification(settings) + email.verify_email_sent(subject, settings['url']) diff --git a/P1P2Tests/userInputs/user_inputs.py b/P1P2Tests/userInputs/user_inputs.py index d6ff74492..6e9d96313 100644 --- a/P1P2Tests/userInputs/user_inputs.py +++ b/P1P2Tests/userInputs/user_inputs.py @@ -29,6 +29,10 @@ class UserData: user_group = "automation_user" web_user = "[Web Users]" + + basic_test_app = ["Basic Tests", "Formplayer Specific Tests", "[Formplayer] Repeats"] + repeat_form_export_name = "Smoke Repeat Form Export" + # Phone Number area_code = "91" @@ -36,6 +40,7 @@ class UserData: app_type = "Applications" case_list_name = 'Case List' form_name = 'Registration Form' + followup_form_name = "Followup Form" login_as = 'henry' update_case_change_link = "Case Change" case_register_form = "Case Register" diff --git a/QA_Requests/Vaccine/README.md b/QA_Requests/Vaccine/README.md index 83f20ad36..74b1fdd48 100644 --- a/QA_Requests/Vaccine/README.md +++ b/QA_Requests/Vaccine/README.md @@ -21,5 +21,5 @@ pip install -r requires.txt - Run tests ```sh -python main.py +python test_new_apk.py ```