diff --git a/web/pgadmin/feature_tests/file_manager_test.py b/web/pgadmin/feature_tests/file_manager_test.py index c76f20386..6e4f52e1d 100644 --- a/web/pgadmin/feature_tests/file_manager_test.py +++ b/web/pgadmin/feature_tests/file_manager_test.py @@ -15,6 +15,7 @@ import time from selenium.webdriver.common.keys import Keys from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.common.by import By +from selenium.webdriver.support import expected_conditions as EC from selenium.common.exceptions import StaleElementReferenceException, \ TimeoutException from regression.feature_utils.base_feature_test import BaseFeatureTest @@ -83,7 +84,7 @@ class CheckFileManagerFeatureTest(BaseFeatureTest): self.page.find_by_css_selector('.change_file_types') self.page.fill_input_by_css_selector( QueryToolLocators.input_file_path_css, - "/tmp/", key_after_input=Keys.RETURN) + "/tmp", key_after_input=Keys.RETURN) if self.page.driver.capabilities['browserName'] == 'firefox': table = self.page.wait_for_element_to_reload( @@ -91,6 +92,12 @@ class CheckFileManagerFeatureTest(BaseFeatureTest): QueryToolLocators.select_file_content_css) ) else: + self.wait.until(EC.visibility_of_element_located( + (By.CSS_SELECTOR, QueryToolLocators.select_file_content_css))) + self.wait.until(lambda element: + self.page.driver.find_element_by_css_selector( + '[name=home]').is_enabled()) + table = self.page.driver.find_element_by_css_selector( QueryToolLocators.select_file_content_css) retry_count = 0 @@ -113,7 +120,8 @@ class CheckFileManagerFeatureTest(BaseFeatureTest): # For XSS we need to search against element's html code assert source_code.find( string_to_find - ) != -1, "{0} might be vulnerable to XSS ".format(source) + ) != -1, "{0} might be vulnerable to XSS, source code is: {1}".format( + source, source_code) def _check_file_sorting(self): load_file = self.page.find_by_css_selector( diff --git a/web/pgadmin/feature_tests/pg_utilities_backup_restore_test.py b/web/pgadmin/feature_tests/pg_utilities_backup_restore_test.py index cc2e89b59..5ae86734c 100644 --- a/web/pgadmin/feature_tests/pg_utilities_backup_restore_test.py +++ b/web/pgadmin/feature_tests/pg_utilities_backup_restore_test.py @@ -108,16 +108,17 @@ class PGUtilitiesBackupFeatureTest(BaseFeatureTest): status = test_utils.get_watcher_dialogue_status(self) - if status != "Successfully completed.": - test_gui_helper.close_bgprocess_popup(self) - - self.assertEquals(status, "Successfully completed.") - self.page.retry_click( (By.CSS_SELECTOR, NavMenuLocators.status_alertifier_more_btn_css), (By.XPATH, NavMenuLocators.process_watcher_alertfier)) + self.page.wait_for_element_to_disappear( + lambda driver: driver.find_element_by_css_selector(".loading-logs") + ) + + if status != "Successfully completed.": + self.assertEquals(status, "Successfully completed.") backup_file = None # Check for XSS in Backup details @@ -177,16 +178,17 @@ class PGUtilitiesBackupFeatureTest(BaseFeatureTest): status = test_utils.get_watcher_dialogue_status(self) - if status != "Successfully completed.": - test_gui_helper.close_bgprocess_popup(self) - - self.assertEquals(status, "Successfully completed.") - self.page.retry_click( (By.CSS_SELECTOR, NavMenuLocators.status_alertifier_more_btn_css), (By.XPATH, NavMenuLocators.process_watcher_alertfier)) + self.page.wait_for_element_to_disappear( + lambda driver: driver.find_element_by_css_selector(".loading-logs") + ) + + if status != "Successfully completed.": + self.assertEquals(status, "Successfully completed.") # Check for XSS in Restore details if self.is_xss_check: diff --git a/web/pgadmin/feature_tests/pg_utilities_maintenance_test.py b/web/pgadmin/feature_tests/pg_utilities_maintenance_test.py index 728323b49..0e6586d0e 100644 --- a/web/pgadmin/feature_tests/pg_utilities_maintenance_test.py +++ b/web/pgadmin/feature_tests/pg_utilities_maintenance_test.py @@ -26,19 +26,19 @@ class PGUtilitiesMaintenanceFeatureTest(BaseFeatureTest): scenarios = [ ("Test for PG maintenance: database", dict( - database_name='pg_maintenance', - table_name='pg_maintenance_table', + database_name='pg_maintenance_', + table_name='table_', test_level='database', is_xss_check=False, )), ("Test for PG maintenance: table", dict( - database_name='pg_maintenance', - table_name='pg_maintenance_table', + database_name='pg_maintenance_', + table_name='table_', test_level='table', is_xss_check=False, )), ("Test for XSS in maintenance dialog", dict( - database_name='pg_maintenance', + database_name='pg_maintenance_', table_name='

test_me

', test_level='table', is_xss_check=True, @@ -67,7 +67,9 @@ class PGUtilitiesMaintenanceFeatureTest(BaseFeatureTest): self.server['sslmode'] ) - self.table_name = self.table_name + str(random.randint(1000, 3000)) + self.table_name = self.table_name + str(random.randint(100, 1000)) + self.database_name = \ + self.database_name + str(random.randint(100, 1000)) test_utils.drop_database(connection, self.database_name) test_utils.create_database(self.server, self.database_name) test_utils.create_table(self.server, self.database_name, @@ -87,7 +89,6 @@ class PGUtilitiesMaintenanceFeatureTest(BaseFeatureTest): self.wait.until(EC.visibility_of_element_located( (By.CSS_SELECTOR, NavMenuLocators.bcg_process_status_alertifier_css))) - self.verify_command() def _open_maintenance_dialogue(self): @@ -101,9 +102,18 @@ class PGUtilitiesMaintenanceFeatureTest(BaseFeatureTest): self.page.toggle_open_tables_node(self.server['name'], self.server['db_password'], self.database_name, 'public') - self.page.click_a_tree_node( - self.table_name, - TreeAreaLocators.sub_nodes_of_tables_node) + retry = 5 + status = False + while retry > 0: + status = self.page.click_a_tree_node( + self.table_name, + TreeAreaLocators.sub_nodes_of_tables_node) + if status: + break + else: + retry -= 1 + self.assertTrue(status, "Table name {} is not selected".format( + self.table_name)) self.page.retry_click( (By.LINK_TEXT, @@ -118,17 +128,17 @@ class PGUtilitiesMaintenanceFeatureTest(BaseFeatureTest): def verify_command(self): status = test_utils.get_watcher_dialogue_status(self) - if status != "Successfully completed.": - - test_gui_helper.close_bgprocess_popup(self) - - self.assertEquals(status, "Successfully completed.") - self.page.retry_click( (By.CSS_SELECTOR, NavMenuLocators.status_alertifier_more_btn_css), (By.XPATH, NavMenuLocators.process_watcher_alertfier)) + self.page.wait_for_element_to_disappear( + lambda driver: driver.find_element_by_css_selector(".loading-logs") + ) + + if status != "Successfully completed.": + self.assertEquals(status, "Successfully completed.") command = self.page.find_by_css_selector( NavMenuLocators. @@ -158,9 +168,9 @@ class PGUtilitiesMaintenanceFeatureTest(BaseFeatureTest): def after(self): test_gui_helper.close_bgprocess_popup(self) - self.page.remove_server(self.server) test_utils.delete_table(self.server, self.database_name, self.table_name) + self.page.remove_server(self.server) connection = test_utils.get_db_connection( self.server['db'], self.server['username'], diff --git a/web/pgadmin/feature_tests/query_tool_tests.py b/web/pgadmin/feature_tests/query_tool_tests.py index 3bcc5e8e4..a0f350320 100644 --- a/web/pgadmin/feature_tests/query_tool_tests.py +++ b/web/pgadmin/feature_tests/query_tool_tests.py @@ -135,18 +135,10 @@ class QueryToolFeatureTest(BaseFeatureTest): query_op.click() # disable auto rollback only if they are enabled - btn = self.page.find_by_css_selector( - QueryToolLocators.btn_auto_rollback) - check = btn.find_element_by_tag_name('i') - if 'visibility-hidden' not in check.get_attribute('class'): - btn.click() + self.uncheck_execute_option('auto_rollback') # enable autocommit only if it's disabled - btn = self.page.find_by_css_selector( - QueryToolLocators.btn_auto_commit) - check = btn.find_element_by_tag_name('i') - if 'visibility-hidden' in check.get_attribute('class'): - btn.click() + self.check_execute_option('auto_commit') # close menu query_op.click() @@ -181,8 +173,7 @@ SELECT generate_series(1, {}) as id1, 'dummy' as id2""".format( print("On demand result set on grid select all... ", file=sys.stderr, end="") - self.page.find_by_css_selector( - QueryToolLocators.btn_execute_query_css).click() + self.page.click_execute_query_button() # wait for header of the table to be visible canvas = self.page.find_by_css_selector( @@ -213,8 +204,7 @@ SELECT generate_series(1, {}) as id1, 'dummy' as id2""".format( print("On demand result set on column select all... ", file=sys.stderr, end="") - self.page.find_by_css_selector( - QueryToolLocators.btn_execute_query_css).click() + self.page.click_execute_query_button() self.page.wait_for_query_tool_loading_indicator_to_disappear() @@ -349,18 +339,16 @@ CREATE TABLE public.{}();""".format(table_name) self.page.fill_codemirror_area_with(query) - # open auto commit option and disable it + # disable auto commit option query_op = self.page.find_by_css_selector( QueryToolLocators.btn_query_dropdown) query_op.click() - self.page.find_by_css_selector( - QueryToolLocators.btn_auto_commit).click() + self.uncheck_execute_option('auto_commit') # close option query_op.click() # execute query - self.page.find_by_css_selector( - QueryToolLocators.btn_execute_query_css).click() + self.page.click_execute_query_button() self.page.wait_for_query_tool_loading_indicator_to_disappear() self.page.click_tab('Messages') @@ -424,13 +412,12 @@ END;""" QueryToolLocators.btn_query_dropdown) query_op.click() - self.page.find_by_css_selector( - QueryToolLocators.btn_auto_commit).click() + # Enable auto_commit if it is disabled + self.check_execute_option('auto_commit') query_op.click() - self.page.find_by_css_selector( - QueryToolLocators.btn_execute_query_css).click() + self.page.click_execute_query_button() self.page.wait_for_query_tool_loading_indicator_to_disappear() @@ -504,14 +491,13 @@ END;""" QueryToolLocators.btn_query_dropdown) query_op.click() - # uncheckt auto commit and check auto-rollback + # uncheck auto commit and check auto-rollback self.uncheck_execute_option('auto_commit') self.check_execute_option('auto_rollback') query_op.click() - self.page.find_by_css_selector( - QueryToolLocators.btn_execute_query_css).click() + self.page.click_execute_query_button() self.page.wait_for_query_tool_loading_indicator_to_disappear() self.page.clear_query_tool() @@ -606,11 +592,20 @@ SELECT 1, pg_sleep(300)""" self.uncheck_execute_option('auto_rollback') # close drop down query_op.click() + # Execute query + retry = 5 + execute_button = self.page.find_by_css_selector( + QueryToolLocators.btn_execute_query_css) + while retry > 0: + execute_button.click() + if self.page.wait_for_query_tool_loading_indicator_to_appear(): + break + else: + retry -= 1 + # Providing a second of sleep since clicks on the execute and stop + # query button is too quick that the query is not able run properly + time.sleep(1) - self.page.find_by_css_selector( - QueryToolLocators.btn_execute_query_css).click() - - self.page.find_by_xpath("//*[@id='fetching_data']") self.page.find_by_css_selector( QueryToolLocators.btn_cancel_query).click() self.page.wait_for_query_tool_loading_indicator_to_disappear() diff --git a/web/pgadmin/feature_tests/view_data_dml_queries.py b/web/pgadmin/feature_tests/view_data_dml_queries.py index 02a449971..14591cdae 100644 --- a/web/pgadmin/feature_tests/view_data_dml_queries.py +++ b/web/pgadmin/feature_tests/view_data_dml_queries.py @@ -308,7 +308,11 @@ CREATE TABLE public.nonintpkey self._verify_row_data(False, updated_row_data) def _add_update_save_row(self, data, row=1): - for idx in data.keys(): + items = list(data.keys()) + for item in range(0, len(items)): + items[item] = int(items[item]) + items.sort(reverse=False) + for idx in items: cell_xpath = CheckForViewDataTest._get_cell_xpath( 'r' + str(idx), row ) @@ -347,9 +351,21 @@ CREATE TABLE public.nonintpkey result_row = self.page.find_by_xpath(xpath) - # List of row values in an array - for idx in config_check_data.keys(): - element = result_row.find_element_by_class_name("r" + str(idx)) + # Verify the List of actual values with the expected list + actual_list = list(config_check_data.keys()) + for value in range(0, len(actual_list)): + actual_list[value] = int(actual_list[value]) + actual_list.sort(reverse=False) + retry = 5 + for idx in actual_list: + while retry > 0: + try: + element = \ + result_row.find_element_by_class_name("r" + str(idx)) + break + except Exception: + print("stale reference exception at id:", idx) + retry -= 1 self.page.driver.execute_script( "arguments[0].scrollIntoView(false)", element) time.sleep(0.4) diff --git a/web/regression/feature_utils/pgadmin_page.py b/web/regression/feature_utils/pgadmin_page.py index a1735b152..61aa4cf5a 100644 --- a/web/regression/feature_utils/pgadmin_page.py +++ b/web/regression/feature_utils/pgadmin_page.py @@ -176,6 +176,18 @@ class PgadminPage: execute_button.click() self.wait_for_query_tool_loading_indicator_to_disappear() + def click_execute_query_button(self): + retry = 5 + execute_button = self.find_by_css_selector( + QueryToolLocators.btn_execute_query_css) + while retry > 0: + execute_button.click() + if self.wait_for_query_tool_loading_indicator_to_appear(): + break + else: + retry -= 1 + self.wait_for_query_tool_loading_indicator_to_disappear() + def check_execute_option(self, option): """"This function will check auto commit or auto roll back based on user input. If button is already checked, no action will be taken""" @@ -394,6 +406,7 @@ class PgadminPage: name_of_database): """will expand database node under databases node""" db_node_expanded_status = False + retry = 5 if self.expand_databases_node(server_name, server_password): sub_nodes_of_databases_node = self.find_by_xpath_list( TreeAreaLocators.sub_nodes_of_databases_node(server_name)) @@ -410,9 +423,17 @@ class PgadminPage: self.driver.execute_script("arguments[0].scrollIntoView()", sub_nodes_of_databases_node[ index_of_required_db_node]) - webdriver.ActionChains(self.driver).double_click( - sub_nodes_of_databases_node[ - index_of_required_db_node]).perform() + while retry > 0: + webdriver.ActionChains(self.driver).double_click( + sub_nodes_of_databases_node[ + index_of_required_db_node]).perform() + if self.check_if_element_exist_by_xpath( + "//div[@class='ajs-header'and text()='INTERNAL SERVER " + "ERROR']", 1): + self.click_modal('OK') + retry -= 1 + else: + break if self.wait_for_elements_to_appear( self.driver, TreeAreaLocators. sub_nodes_of_database_node( @@ -935,7 +956,7 @@ class PgadminPage: return False return True - except NoSuchElementException: + except (NoSuchElementException, StaleElementReferenceException): return True return self._wait_for("element to disappear", element_if_it_disappears) @@ -976,9 +997,10 @@ class PgadminPage: self._wait_for("spinner to disappear", spinner_has_disappeared, 20) def wait_for_query_tool_loading_indicator_to_appear(self): - self.check_if_element_exist_by_xpath( + status = self.check_if_element_exist_by_xpath( "//div[@id='editor-panel']//" - "div[@class='pg-sp-container sql-editor-busy-fetching']") + "div[@class='pg-sp-container sql-editor-busy-fetching']", 1) + return status def wait_for_app(self): def page_shows_app(driver): diff --git a/web/regression/runtests.py b/web/regression/runtests.py index 540eae65e..8c52753f3 100644 --- a/web/regression/runtests.py +++ b/web/regression/runtests.py @@ -234,6 +234,8 @@ def get_test_modules(arguments): if 'headless_chrome' in test_setup.config_data: if test_setup.config_data['headless_chrome']: options.add_argument("--headless") + options.add_argument("--no-sandbox") + options.add_argument("--disable-setuid-sandbox") options.add_argument("--window-size=1280,1024") options.add_argument("--disable-infobars") options.add_experimental_option('w3c', False)