From 9479f0e632d278e56ad0d63ace2b6976e81b250b Mon Sep 17 00:00:00 2001 From: Yogesh Mahajan Date: Wed, 10 Nov 2021 11:50:20 +0530 Subject: [PATCH] Fixed feature test cases after react porting. --- .../feature_tests/browser_tool_bar_test.py | 28 +- ...opy_selected_query_results_feature_test.py | 9 +- .../feature_tests/file_manager_test.py | 6 +- .../feature_tests/keyboard_shortcut_test.py | 4 +- .../pg_datatype_validation_test.py | 14 +- .../pg_utilities_backup_restore_test.py | 6 +- .../pg_utilities_maintenance_test.py | 38 +- .../query_tool_auto_complete_tests.py | 13 +- .../feature_tests/query_tool_journey_test.py | 27 +- web/pgadmin/feature_tests/query_tool_tests.py | 22 +- .../feature_tests/table_ddl_feature_test.py | 15 +- .../test_copy_sql_to_query_tool.py | 18 +- .../feature_tests/view_data_dml_queries.py | 37 +- .../xss_checks_panels_and_query_tool_test.py | 33 +- .../xss_checks_pgadmin_debugger_test.py | 16 +- .../xss_checks_roles_control_test.py | 30 +- web/regression/feature_utils/locators.py | 13 +- web/regression/feature_utils/pgadmin_page.py | 941 ++++++++++-------- .../feature_utils/tree_area_locators.py | 336 +++++-- .../python_test_utils/test_utils.py | 26 + web/regression/requirements.txt | 2 +- web/regression/runtests.py | 4 +- 22 files changed, 940 insertions(+), 698 deletions(-) diff --git a/web/pgadmin/feature_tests/browser_tool_bar_test.py b/web/pgadmin/feature_tests/browser_tool_bar_test.py index a4544daf1..88ad7b889 100644 --- a/web/pgadmin/feature_tests/browser_tool_bar_test.py +++ b/web/pgadmin/feature_tests/browser_tool_bar_test.py @@ -47,7 +47,7 @@ class BrowserToolBarFeatureTest(BaseFeatureTest): file=sys.stderr, end="") self.test_view_data_tool_button() print("OK.", file=sys.stderr) - # + # Check for filtered rows button print("\nFiltered Rows ToolBar Button ", file=sys.stderr, end="") @@ -60,28 +60,24 @@ class BrowserToolBarFeatureTest(BaseFeatureTest): self.test_table_name) def test_query_tool_button(self): - self.page.expand_database_node( - self.server['name'], - self.server['db_password'], self.test_db) + self.page.expand_database_node("Servers", self.server['name'], + self.server['db_password'], + self.test_db) self.assertTrue(self.page.retry_click( (By.CSS_SELECTOR, BrowserToolBarLocators.open_query_tool_button_css), (By.CSS_SELECTOR, BrowserToolBarLocators.query_tool_panel_css)), 'Query tool did not open on clicking Query Tool button.') + self.page.close_query_tool(prompt=False) def test_view_data_tool_button(self): - self.page.click_a_tree_node( - self.test_db, - TreeAreaLocators.sub_nodes_of_databases_node(self.server['name'])) - self.page.toggle_open_schema_node( - self.server['name'], self.server['db_password'], - self.test_db, 'public') - self.page.toggle_open_tables_node( - self.server['name'], self.server['db_password'], - self.test_db, 'public') - self.page.click_a_tree_node( - self.test_table_name, - TreeAreaLocators.sub_nodes_of_tables_node) + self.page.expand_tables_node("Servers", self.server['name'], + self.server['db_password'], self.test_db, + "public") + + table_node = self.page.check_if_element_exists_with_scroll( + TreeAreaLocators.table_node(self.test_table_name)) + table_node.click() self.assertTrue(self.page.retry_click( (By.CSS_SELECTOR, diff --git a/web/pgadmin/feature_tests/copy_selected_query_results_feature_test.py b/web/pgadmin/feature_tests/copy_selected_query_results_feature_test.py index 8e2caa5dd..619b9af3a 100644 --- a/web/pgadmin/feature_tests/copy_selected_query_results_feature_test.py +++ b/web/pgadmin/feature_tests/copy_selected_query_results_feature_test.py @@ -8,6 +8,7 @@ ########################################################################## import random +import time from selenium.webdriver import ActionChains from selenium.webdriver.common.keys import Keys @@ -37,9 +38,9 @@ class CopySelectedQueryResultsFeatureTest(BaseFeatureTest): self.server, self.test_db, self.test_table_name) def runTest(self): - self.page.expand_database_node( - self.server['name'], - self.server['db_password'], self.test_db) + self.page.expand_database_node("Servers", self.server['name'], + self.server['db_password'], + self.test_db) self.page.open_query_tool() self.page.fill_codemirror_area_with( @@ -60,7 +61,7 @@ class CopySelectedQueryResultsFeatureTest(BaseFeatureTest): def paste_values_to_scratch_pad(self): self.page.driver.switch_to.default_content() - self.page.driver.switch_to_frame( + self.page.driver.switch_to.frame( self.page.driver.find_element_by_tag_name("iframe")) scratch_pad_ele = self.page.find_by_css_selector( QueryToolLocators.scratch_pad_css) diff --git a/web/pgadmin/feature_tests/file_manager_test.py b/web/pgadmin/feature_tests/file_manager_test.py index ac9f25c9f..58561449b 100644 --- a/web/pgadmin/feature_tests/file_manager_test.py +++ b/web/pgadmin/feature_tests/file_manager_test.py @@ -67,9 +67,9 @@ class CheckFileManagerFeatureTest(BaseFeatureTest): print("OK.", file=sys.stderr) def _navigate_to_query_tool(self): - self.page.expand_database_node( - self.server['name'], - self.server['db_password'], self.test_db) + self.page.expand_database_node("Server", self.server['name'], + self.server['db_password'], + self.test_db) self.page.open_query_tool() def _create_new_file(self): diff --git a/web/pgadmin/feature_tests/keyboard_shortcut_test.py b/web/pgadmin/feature_tests/keyboard_shortcut_test.py index 06965d7af..de99818a1 100644 --- a/web/pgadmin/feature_tests/keyboard_shortcut_test.py +++ b/web/pgadmin/feature_tests/keyboard_shortcut_test.py @@ -133,7 +133,7 @@ class KeyboardShortcutFeatureTest(BaseFeatureTest): "and contains(.,'" + locator + "')]" ) - field = file_menu.find_element_by_name('key') + field = file_menu.find_element(By.NAME, 'key') field.click() field.send_keys(key) @@ -141,5 +141,5 @@ class KeyboardShortcutFeatureTest(BaseFeatureTest): self.page.click_modal('Save') self.page.wait_for_element_to_disappear( - lambda driver: driver.find_element_by_css_selector(".ajs-modal") + lambda driver: driver.find_element(By.CSS_SELECTOR, ".ajs-modal") ) diff --git a/web/pgadmin/feature_tests/pg_datatype_validation_test.py b/web/pgadmin/feature_tests/pg_datatype_validation_test.py index da0e8b683..cbc43a1e0 100644 --- a/web/pgadmin/feature_tests/pg_datatype_validation_test.py +++ b/web/pgadmin/feature_tests/pg_datatype_validation_test.py @@ -154,7 +154,9 @@ class PGDataypeFeatureTest(BaseFeatureTest): def runTest(self): self.page.wait_for_spinner_to_disappear() self.page.add_server(self.server) - self._schema_node_expandable() + self.page.expand_database_node("Server", self.server['name'], + self.server['db_password'], + self.test_db) # Check data types self._check_datatype() @@ -163,17 +165,15 @@ class PGDataypeFeatureTest(BaseFeatureTest): def after(self): self.page.remove_server(self.server) + # TODO - To be remove def _schema_node_expandable(self): - self.page.expand_database_node( - self.server['name'], - self.server['db_password'], self.test_db) + self.page.expand_database_node("Server", self.server['name'], + self.server['db_password'], + self.test_db) def _check_datatype(self): # Slick grid does not render all the column if viewport is not enough # wide. So execute test as batch of queries. - self.page.click_a_tree_node( - self.test_db, - TreeAreaLocators.sub_nodes_of_databases_node(self.server['name'])) self.page.open_query_tool() self._create_enum_type() for batch in config_data: 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 78c2d85b5..9a8650bb2 100644 --- a/web/pgadmin/feature_tests/pg_utilities_backup_restore_test.py +++ b/web/pgadmin/feature_tests/pg_utilities_backup_restore_test.py @@ -67,9 +67,9 @@ class PGUtilitiesBackupFeatureTest(BaseFeatureTest): self.wait = WebDriverWait(self.page.driver, 20) def runTest(self): - self.page.expand_database_node( - self.server['name'], - self.server['db_password'], self.database_name) + self.page.expand_database_node("Server", self.server['name'], + self.server['db_password'], + self.database_name) # Backup self.initiate_backup() diff --git a/web/pgadmin/feature_tests/pg_utilities_maintenance_test.py b/web/pgadmin/feature_tests/pg_utilities_maintenance_test.py index f9594a47d..344e6b2c4 100644 --- a/web/pgadmin/feature_tests/pg_utilities_maintenance_test.py +++ b/web/pgadmin/feature_tests/pg_utilities_maintenance_test.py @@ -91,29 +91,25 @@ class PGUtilitiesMaintenanceFeatureTest(BaseFeatureTest): self.verify_command() def _open_maintenance_dialogue(self): - self.page.expand_database_node( - self.server['name'], - self.server['db_password'], self.database_name) if self.test_level == 'table': - self.page.toggle_open_schema_node(self.server['name'], - self.server['db_password'], - self.database_name, 'public') - self.page.toggle_open_tables_node(self.server['name'], - self.server['db_password'], - self.database_name, 'public') - 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.expand_tables_node("Server", self.server['name'], + self.server['db_password'], + self.database_name, 'public') + table_node = self.page.check_if_element_exists_with_scroll( + TreeAreaLocators.table_node(self.table_name)) + + status = False + if table_node: + status = True + self.assertTrue(status, "Table name {} is not visible/selected". + format(self.table_name)) + table_node.click() + + else: + self.page.expand_database_node("Server", self.server['name'], + self.server['db_password'], + self.database_name) self.page.retry_click( (By.LINK_TEXT, NavMenuLocators.tools_menu_link_text), diff --git a/web/pgadmin/feature_tests/query_tool_auto_complete_tests.py b/web/pgadmin/feature_tests/query_tool_auto_complete_tests.py index d384ebfc0..9e354fe34 100644 --- a/web/pgadmin/feature_tests/query_tool_auto_complete_tests.py +++ b/web/pgadmin/feature_tests/query_tool_auto_complete_tests.py @@ -12,6 +12,7 @@ import random from selenium.webdriver import ActionChains from selenium.webdriver.common.keys import Keys +from selenium.webdriver.common.by import By from regression.python_test_utils import test_utils from regression.feature_utils.base_feature_test import BaseFeatureTest from regression.feature_utils.locators import QueryToolLocators @@ -55,9 +56,9 @@ class QueryToolAutoCompleteFeatureTest(BaseFeatureTest): test_utils.create_table(self.server, self.test_db, self.second_table_name) - self.page.expand_database_node( - self.server['name'], - self.server['db_password'], self.test_db) + self.page.expand_database_node("Server", self.server['name'], + self.server['db_password'], + self.test_db) self.page.open_query_tool() self.page.wait_for_spinner_to_disappear() @@ -171,7 +172,7 @@ class QueryToolAutoCompleteFeatureTest(BaseFeatureTest): Keys.CONTROL).send_keys(Keys.SPACE).key_up( Keys.CONTROL).perform() if self.page.check_if_element_exist_by_xpath( - QueryToolLocators.code_mirror_hint_box_xpath, 20): + QueryToolLocators.code_mirror_hint_box_xpath, 15): hint_displayed = True break else: @@ -184,8 +185,8 @@ class QueryToolAutoCompleteFeatureTest(BaseFeatureTest): else: # if no IntelliSense is present it means there is only one option # so check if required string is present in codeMirror - code_mirror = self.driver.find_elements_by_xpath( - QueryToolLocators.code_mirror_data_xpath) + code_mirror = self.driver.find_elements( + By.XPATH, QueryToolLocators.code_mirror_data_xpath) for data in code_mirror: code_mirror_text = data.text print("Single entry..........") diff --git a/web/pgadmin/feature_tests/query_tool_journey_test.py b/web/pgadmin/feature_tests/query_tool_journey_test.py index 4ec636302..c0e7f442c 100644 --- a/web/pgadmin/feature_tests/query_tool_journey_test.py +++ b/web/pgadmin/feature_tests/query_tool_journey_test.py @@ -12,6 +12,7 @@ import random from selenium.webdriver import ActionChains from selenium.webdriver.common.keys import Keys +from selenium.webdriver.common.by import By from selenium.webdriver.support.ui import WebDriverWait from regression.python_test_utils import test_utils from regression.feature_utils.base_feature_test import BaseFeatureTest @@ -94,7 +95,7 @@ class QueryToolJourneyTest(BaseFeatureTest): def _test_copies_rows(self): self.page.driver.switch_to.default_content() - self.page.driver.switch_to_frame( + self.page.driver.switch_to.frame( self.page.driver.find_element_by_tag_name("iframe")) select_row = self.page.find_by_xpath( @@ -106,7 +107,7 @@ class QueryToolJourneyTest(BaseFeatureTest): copy_row.click() self.page.driver.switch_to.default_content() - self.page.driver.switch_to_frame( + self.page.driver.switch_to.frame( self.page.driver.find_element_by_tag_name("iframe")) scratch_pad_ele = self.page.find_by_css_selector( @@ -121,7 +122,7 @@ class QueryToolJourneyTest(BaseFeatureTest): def _test_copies_columns(self): self.page.driver.switch_to.default_content() - self.page.driver.switch_to_frame( + self.page.driver.switch_to.frame( self.page.driver.find_element_by_tag_name("iframe")) column_header = self.page.find_by_css_selector( @@ -133,7 +134,7 @@ class QueryToolJourneyTest(BaseFeatureTest): copy_btn.click() self.page.driver.switch_to.default_content() - self.page.driver.switch_to_frame( + self.page.driver.switch_to.frame( self.page.driver.find_element_by_tag_name("iframe")) scratch_pad_ele = self.page.find_by_css_selector( @@ -169,13 +170,13 @@ class QueryToolJourneyTest(BaseFeatureTest): failed_history_detail_pane.text ) self.page.wait_for_elements( - lambda driver: driver.find_elements_by_css_selector( - QueryToolLocators.query_history_entries)) + lambda driver: driver.find_elements( + By.CSS_SELECTOR, QueryToolLocators.query_history_entries)) # get the query history rows and click the previous query row which # was executed and verify it - history_rows = self.driver.find_elements_by_css_selector( - QueryToolLocators.query_history_entries) + history_rows = self.driver.find_elements( + By.CSS_SELECTOR, QueryToolLocators.query_history_entries) history_rows[1].click() selected_history_entry = self.page.find_by_css_selector( @@ -209,8 +210,8 @@ class QueryToolJourneyTest(BaseFeatureTest): self.page.click_tab(self.query_history_tab_name) query_list = self.page.wait_for_elements( - lambda driver: driver.find_elements_by_css_selector( - QueryToolLocators.query_history_entries)) + lambda driver: driver.find_elements( + By.CSS_SELECTOR, QueryToolLocators.query_history_entries)) self.assertTrue(17, len(query_list)) @@ -420,9 +421,9 @@ class QueryToolJourneyTest(BaseFeatureTest): self.page.click_modal('Yes') def _navigate_to_query_tool(self): - self.page.expand_database_node( - self.server['name'], - self.server['db_password'], self.test_db) + self.page.expand_database_node("Server", self.server['name'], + self.server['db_password'], + self.test_db) self.page.open_query_tool() self.page.wait_for_spinner_to_disappear() diff --git a/web/pgadmin/feature_tests/query_tool_tests.py b/web/pgadmin/feature_tests/query_tool_tests.py index 8cdb164d4..1de2686de 100644 --- a/web/pgadmin/feature_tests/query_tool_tests.py +++ b/web/pgadmin/feature_tests/query_tool_tests.py @@ -36,9 +36,9 @@ class QueryToolFeatureTest(BaseFeatureTest): def before(self): self.page.wait_for_spinner_to_disappear() self.page.add_server(self.server) - self.page.expand_database_node( - self.server['name'], - self.server['db_password'], self.test_db) + self.page.expand_database_node("Server", self.server['name'], + self.server['db_password'], + self.test_db) self.page.open_query_tool() self.page.wait_for_spinner_to_disappear() self._reset_options() @@ -128,7 +128,7 @@ class QueryToolFeatureTest(BaseFeatureTest): QueryToolLocators.btn_explain_buffers, QueryToolLocators.btn_explain_timing): btn = self.page.find_by_css_selector(op) - check = btn.find_element_by_tag_name('i') + check = btn.find_element(By.TAG_NAME, 'i') if 'visibility-hidden' not in check.get_attribute('class'): btn.click() @@ -286,10 +286,10 @@ SELECT generate_series(1, 1000) as id order by id desc""" ) # Search for 'Output' word in result (verbose option) - canvas.find_element_by_xpath("//*[contains(string(), 'Output')]") + canvas.find_element(By.XPATH, "//*[contains(string(), 'Output')]") # Search for 'Total Cost' word in result (cost option) - canvas.find_element_by_xpath("//*[contains(string(),'Total Cost')]") + canvas.find_element(By.XPATH, "//*[contains(string(),'Total Cost')]") def _query_tool_explain_analyze_with_buffers_and_timing(self): query = """-- Explain analyze query with buffers and timing @@ -382,8 +382,8 @@ SELECT relname FROM pg_catalog.pg_class canvas = self.wait.until(EC.presence_of_element_located( (By.CSS_SELECTOR, QueryToolLocators.query_output_canvas_css))) - el = canvas.find_elements_by_xpath( - QueryToolLocators.output_column_data_xpath.format(table_name)) + el = canvas.find_elements(By.XPATH, QueryToolLocators. + output_column_data_xpath.format(table_name)) assert len(el) == 0, "Table '{}' created with auto commit disabled " \ "and without any explicit commit.".format( @@ -699,7 +699,7 @@ SELECT 1, pg_sleep(300)""" QueryToolLocators.btn_explain_buffers, QueryToolLocators.btn_explain_timing): btn = self.page.find_by_css_selector(op) - check = btn.find_element_by_tag_name('i') + check = btn.find_element(By.TAG_NAME, 'i') if 'visibility-hidden' not in check.get_attribute('class'): btn.click() # click cost button @@ -720,7 +720,7 @@ SELECT 1, pg_sleep(300)""" (By.CSS_SELECTOR, QueryToolLocators.query_output_canvas_css)) ) # Search for 'Output' word in result (verbose option) - canvas.find_element_by_xpath("//*[contains(string(), 'JIT')]") + canvas.find_element(By.XPATH, "//*[contains(string(), 'JIT')]") self.page.clear_query_tool() @@ -732,7 +732,7 @@ class WaitForAnyElementWithText(object): def __call__(self, driver): try: - elements = EC._find_elements(driver, self.locator) + elements = driver.find_elements(*self.locator) for elem in elements: if self.text in elem.text: return True diff --git a/web/pgadmin/feature_tests/table_ddl_feature_test.py b/web/pgadmin/feature_tests/table_ddl_feature_test.py index d191019ca..bddab4df8 100644 --- a/web/pgadmin/feature_tests/table_ddl_feature_test.py +++ b/web/pgadmin/feature_tests/table_ddl_feature_test.py @@ -31,16 +31,13 @@ class TableDdlFeatureTest(BaseFeatureTest): self.test_table_name = "test_table" + str(random.randint(1000, 3000)) test_utils.create_table(self.server, self.test_db, self.test_table_name) + self.page.expand_tables_node("Server", self.server['name'], + self.server['db_password'], self.test_db, + 'public') + table_node = self.page.check_if_element_exists_with_scroll( + TreeAreaLocators.table_node(self.test_table_name)) + table_node.click() - self.page.expand_database_node( - self.server['name'], - self.server['db_password'], self.test_db) - self.page.toggle_open_tables_node( - self.server['name'], self.server['db_password'], - self.test_db, 'public') - self.page.click_a_tree_node( - self.test_table_name, - TreeAreaLocators.sub_nodes_of_tables_node) self.page.click_tab("SQL") # Wait till data is displayed in SQL Tab diff --git a/web/pgadmin/feature_tests/test_copy_sql_to_query_tool.py b/web/pgadmin/feature_tests/test_copy_sql_to_query_tool.py index a08532fa7..f4b6ded7f 100644 --- a/web/pgadmin/feature_tests/test_copy_sql_to_query_tool.py +++ b/web/pgadmin/feature_tests/test_copy_sql_to_query_tool.py @@ -73,7 +73,7 @@ class CopySQLFeatureTest(BaseFeatureTest): time.sleep(5) self.driver.switch_to.default_content() - self.driver.switch_to_frame( + self.driver.switch_to.frame( self.driver.find_element_by_tag_name("iframe")) code_mirror = self.driver.find_elements_by_xpath( @@ -89,16 +89,12 @@ class CopySQLFeatureTest(BaseFeatureTest): self.test_table_name = "test_table" + str(random.randint(1000, 3000)) test_utils.create_table(self.server, self.test_db, self.test_table_name) - - self.page.expand_database_node( - self.server['name'], - self.server['db_password'], self.test_db) - self.page.toggle_open_tables_node( - self.server['name'], self.server['db_password'], - self.test_db, 'public') - self.page.click_a_tree_node( - self.test_table_name, - TreeAreaLocators.sub_nodes_of_tables_node) + self.page.expand_tables_node("Server", self.server['name'], + self.server['db_password'], self.test_db, + 'public') + table_node = self.page.check_if_element_exists_with_scroll( + TreeAreaLocators.table_node(self.test_table_name)) + table_node.click() def _update_preferences_setting(self): file_menu = self.page.find_by_css_selector( diff --git a/web/pgadmin/feature_tests/view_data_dml_queries.py b/web/pgadmin/feature_tests/view_data_dml_queries.py index 93e20c130..24f04719e 100644 --- a/web/pgadmin/feature_tests/view_data_dml_queries.py +++ b/web/pgadmin/feature_tests/view_data_dml_queries.py @@ -121,13 +121,9 @@ CREATE TABLE public.nonintpkey def runTest(self): self.page.wait_for_spinner_to_disappear() self.page.add_server(self.server) - - self.page.expand_database_node( - self.server['name'], - self.server['db_password'], self.test_db) - self.page.toggle_open_tables_node(self.server['name'], - self.server['db_password'], - self.test_db, 'public') + self.page.expand_tables_node("Server", self.server['name'], + self.server['db_password'], self.test_db, + 'public') self._load_config_data('table_insert_update_cases') data_local = config_data @@ -169,12 +165,17 @@ CREATE TABLE public.nonintpkey config_data = config_data_json[config_key] def _perform_test_for_table(self, table_name, config_data_local): - self.page.click_a_tree_node( - table_name, - TreeAreaLocators.sub_nodes_of_tables_node) + # self.page.click_a_tree_node( + # table_name, + # TreeAreaLocators.sub_nodes_of_tables_node) + table_node = self.page.check_if_element_exists_with_scroll( + TreeAreaLocators.table_node(table_name)) + table_node.click() + # Open Object -> View/Edit data self._view_data_grid(table_name) + time.sleep(3) self.page.wait_for_query_tool_loading_indicator_to_disappear() # Run test to insert a new row in table with default values self._add_row(config_data_local) @@ -237,7 +238,7 @@ CREATE TABLE public.nonintpkey if cell_type in ['int', 'int[]']: if value == 'clear': - cell_el.find_element_by_css_selector('input').clear() + cell_el.find_element(By.CSS_SELECTOR, 'input').clear() else: ActionChains(self.driver).send_keys(value). \ send_keys(Keys.ENTER).perform() @@ -273,13 +274,13 @@ CREATE TABLE public.nonintpkey else: # Boolean editor test for to True click if data[1] == 'true': - checkbox_el = cell_el.find_element_by_xpath( - ".//*[contains(@class, 'multi-checkbox')]") + checkbox_el = cell_el.find_element( + By.XPATH, ".//*[contains(@class, 'multi-checkbox')]") checkbox_el.click() # Boolean editor test for to False click elif data[1] == 'false': - checkbox_el = cell_el.find_element_by_xpath( - ".//*[contains(@class, 'multi-checkbox')]") + checkbox_el = cell_el.find_element( + By.XPATH, ".//*[contains(@class, 'multi-checkbox')]") # Sets true checkbox_el.click() # Sets false @@ -307,7 +308,7 @@ CREATE TABLE public.nonintpkey ), CheckForViewDataTest.TIMEOUT_STRING ) self.page.driver.switch_to.frame( - self.page.driver.find_element_by_tag_name('iframe') + self.page.driver.find_element(By.TAG_NAME, 'iframe') ) def _copy_paste_row(self, config_data_l): @@ -380,7 +381,7 @@ CREATE TABLE public.nonintpkey try: result_row = self.page.find_by_xpath(xpath) element = \ - result_row.find_element_by_class_name("r" + str(idx)) + result_row.find_element(By.CLASS_NAME, "r" + str(idx)) self.page.driver.execute_script( scroll_on_arg_for_js, element) break @@ -398,6 +399,6 @@ CREATE TABLE public.nonintpkey list_item.sort(reverse=True) for idx in list_item: time.sleep(0.4) - element = result_row.find_element_by_class_name("r" + str(idx)) + element = result_row.find_element(By.CLASS_NAME, "r" + str(idx)) self.page.driver.execute_script( scroll_on_arg_for_js, element) diff --git a/web/pgadmin/feature_tests/xss_checks_panels_and_query_tool_test.py b/web/pgadmin/feature_tests/xss_checks_panels_and_query_tool_test.py index 93971eb86..5cda88be7 100644 --- a/web/pgadmin/feature_tests/xss_checks_panels_and_query_tool_test.py +++ b/web/pgadmin/feature_tests/xss_checks_panels_and_query_tool_test.py @@ -9,12 +9,14 @@ import sys import random +import time from regression.python_test_utils import test_utils from regression.feature_utils.base_feature_test import BaseFeatureTest from selenium.webdriver import ActionChains from selenium.common.exceptions import StaleElementReferenceException, \ WebDriverException +from selenium.webdriver.common.by import By from regression.feature_utils.locators import QueryToolLocators from regression.feature_utils.tree_area_locators import TreeAreaLocators @@ -74,7 +76,6 @@ class CheckForXssFeatureTest(BaseFeatureTest): while retry > 0: try: self.page.refresh_page() - self.page.toggle_open_servers_group() self._tables_node_expandable() self._check_xss_in_dependents_tab() retry = 0 @@ -106,15 +107,13 @@ class CheckForXssFeatureTest(BaseFeatureTest): self.server, self.test_db, self.test_table_name) def _tables_node_expandable(self): - self.page.expand_database_node( - self.server['name'], - self.server['db_password'], self.test_db) - self.page.toggle_open_tables_node(self.server['name'], - self.server['db_password'], - self.test_db, 'public') - self.page.click_a_tree_node( - self.test_table_name, - TreeAreaLocators.sub_nodes_of_tables_node) + self.page.expand_tables_node("Server", self.server['name'], + self.server['db_password'], self.test_db, + 'public') + + table_node = self.page.check_if_element_exists_with_scroll( + TreeAreaLocators.table_node(self.test_table_name)) + table_node.click() def _check_xss_in_browser_tree(self): print( @@ -138,6 +137,12 @@ class CheckForXssFeatureTest(BaseFeatureTest): file=sys.stderr, end="" ) self.page.click_tab("SQL") + + # Wait till data is displayed in SQL Tab + self.assertTrue(self.page.check_if_element_exist_by_xpath( + "//*[contains(@class,'CodeMirror-lines') and " + "contains(.,'CREATE TABLE')]", 10), "No data displayed in SQL tab") + # Fetch the inner html & check for escaped characters source_code = self.page.find_by_xpath( "//*[contains(@class,'CodeMirror-lines') and " @@ -197,7 +202,7 @@ class CheckForXssFeatureTest(BaseFeatureTest): "contains(@style, 'top:0px')]" ) - cells = result_row.find_elements_by_tag_name('div') + cells = result_row.find_elements(By.TAG_NAME, 'div') # remove first element as it is row number. source_code = cells[1].get_attribute('innerHTML') @@ -239,8 +244,8 @@ class CheckForXssFeatureTest(BaseFeatureTest): while retry > 0: try: history_ele = self.driver \ - .find_element_by_css_selector( - ".query-detail .content-value") + .find_element(By.CSS_SELECTOR, + ".query-detail .content-value") source_code = history_ele.get_attribute('innerHTML') break except StaleElementReferenceException: @@ -279,7 +284,7 @@ class CheckForXssFeatureTest(BaseFeatureTest): ) self.page.find_by_css_selector(".slick-header-column") - cells = self.driver.\ + cells = self.driver. \ find_elements_by_css_selector(".slick-header-column") # remove first element as it is row number. diff --git a/web/pgadmin/feature_tests/xss_checks_pgadmin_debugger_test.py b/web/pgadmin/feature_tests/xss_checks_pgadmin_debugger_test.py index 79ac785be..c04f1ad0f 100644 --- a/web/pgadmin/feature_tests/xss_checks_pgadmin_debugger_test.py +++ b/web/pgadmin/feature_tests/xss_checks_pgadmin_debugger_test.py @@ -58,16 +58,12 @@ class CheckDebuggerForXssFeatureTest(BaseFeatureTest): self.function_name) def _function_node_expandable(self): - self.page.expand_database_node( - self.server['name'], - self.server['db_password'], self.test_db) - self.page.toggle_open_schema_node(self.server['name'], - self.server['db_password'], - self.test_db, 'public') - self.page.toggle_open_function_node() - self.page.click_a_tree_node( - self.function_name + "()", - TreeAreaLocators.sub_nodes_of_functions_node) + self.page.expand_schema_child_node("Server", self.server['name'], + self.server['db_password'], + self.test_db, 'public', "Functions") + function_node = self.page.check_if_element_exists_with_scroll( + TreeAreaLocators.function_node(self.function_name + "()")) + function_node.click() def _debug_function(self): self.page.driver.find_element_by_link_text("Object").click() diff --git a/web/pgadmin/feature_tests/xss_checks_roles_control_test.py b/web/pgadmin/feature_tests/xss_checks_roles_control_test.py index 4aeecb4e0..d51632386 100644 --- a/web/pgadmin/feature_tests/xss_checks_roles_control_test.py +++ b/web/pgadmin/feature_tests/xss_checks_roles_control_test.py @@ -42,6 +42,8 @@ class CheckRoleMembershipControlFeatureTest(BaseFeatureTest): self.role) test_utils.create_role(self.server, "postgres", "

test

") + test_utils.grant_role(self.server, "postgres", + self.role, "

test

") self.wait = WebDriverWait(self.page.driver, 20) def runTest(self): @@ -58,11 +60,13 @@ class CheckRoleMembershipControlFeatureTest(BaseFeatureTest): "

test

") def _role_node_expandable(self, role): - self.page.expand_server_node( - self.server['name'], self.server['db_password']) - self.page.toggle_open_tree_item('Login/Group Roles') - self.page.click_a_tree_node( - role, TreeAreaLocators.sub_nodes_of_login_group_node) + self.page.expand_server_child_node("Server", self.server['name'], + self.server['db_password'], + 'Login/Group Roles') + + role_node = self.page.check_if_element_exists_with_scroll( + TreeAreaLocators.role_node(role)) + role_node.click() def _check_role_membership_control(self): self.page.driver.find_element_by_link_text( @@ -70,24 +74,22 @@ class CheckRoleMembershipControlFeatureTest(BaseFeatureTest): property_object = self.wait.until(EC.visibility_of_element_located( (By.CSS_SELECTOR, NavMenuLocators.properties_obj_css))) property_object.click() - WebDriverWait(self.page.driver, 4).until( + membership_tab = WebDriverWait(self.page.driver, 4).until( EC.presence_of_element_located(( - By.XPATH, "//a[normalize-space(text())='Membership']"))) - self.click_membership_tab() + By.XPATH, "//span[normalize-space(text())='Membership']"))) + membership_tab.click() + # Fetch the source code for our custom control source_code = self.page.find_by_xpath( - "//div[contains(@class,'rolmembership')]" - ).get_attribute('innerHTML') + "//span[contains(@class,'icon-')]/following-sibling::span" + ).text self._check_escaped_characters( source_code, '<h1>test</h1>', 'Role Membership Control' ) - self.page.find_by_xpath( - "//button[contains(@type, 'cancel') and " - "contains(.,'Cancel')]" - ).click() + self.page.find_by_xpath("//button/span[text()='Close']").click() def _check_escaped_characters(self, source_code, string_to_find, source): # For XSS we need to search against element's html code diff --git a/web/regression/feature_utils/locators.py b/web/regression/feature_utils/locators.py index 4c57f344b..3c728ca9c 100644 --- a/web/regression/feature_utils/locators.py +++ b/web/regression/feature_utils/locators.py @@ -249,8 +249,8 @@ class ConnectToServerDiv: password_field = "//input[@id='password']" ok_button = \ - "//div [@class='alertify ajs-modeless ajs-movable ajs-zoom']" \ - "//button[text()='OK']" + "//button[@class='ajs-button btn btn-primary fa fa-check " \ + "pg-alertify-button']" error_message = \ "//form[@id='frmPassword']/div/div//div[@class='alert-text']" @@ -258,3 +258,12 @@ class ConnectToServerDiv: cancel_button = \ "//div [@class='alertify ajs-modeless ajs-movable ajs-zoom']" \ "//button[text()='Cancel']" + + +class PropertyDialogueLocators: + # This will contain xpaths for elements in properties dialogue + server_dialogue_title = "//div[text()='Create - Server']" + + server_connection_tab = "//button/span[text()='Connection']" + + server_tab_save = "//button/span[text()='Save']" diff --git a/web/regression/feature_utils/pgadmin_page.py b/web/regression/feature_utils/pgadmin_page.py index c44f62358..e648bc625 100644 --- a/web/regression/feature_utils/pgadmin_page.py +++ b/web/regression/feature_utils/pgadmin_page.py @@ -20,7 +20,7 @@ from selenium.webdriver.support import expected_conditions as EC from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.common.by import By from regression.feature_utils.locators import QueryToolLocators, \ - NavMenuLocators, ConnectToServerDiv + NavMenuLocators, ConnectToServerDiv, PropertyDialogueLocators from regression.feature_utils.tree_area_locators import TreeAreaLocators @@ -37,6 +37,7 @@ class PgadminPage: self.timeout = 30 self.app_start_timeout = 90 + # pgAdmin related methods def login_to_app(self, user_detail): if not (self.check_if_element_exist_by_xpath( '//a[@id="navbar-user"]', 1)): @@ -90,60 +91,61 @@ class PgadminPage: self.click_element(modal_button) def add_server(self, server_config): - self.find_by_xpath( - "//*[@class='aciTreeText' and contains(.,'Servers')]").click() - - if self.driver.name == 'firefox': - ActionChains(self.driver).context_click(self.find_by_xpath( - "//*[@class='aciTreeText' and contains(.,'Servers')]"))\ - .perform() - ActionChains(self.driver).move_to_element( - self.find_by_xpath("//li/span[text()='Create']")).perform() - self.find_by_xpath("//li/span[text()='Server...']").click() - else: - self.driver.find_element_by_link_text("Object").click() - ActionChains(self.driver).move_to_element( - self.driver.find_element_by_link_text("Create")).perform() - self.find_by_partial_link_text("Server...").click() + server_group_node = \ + self.find_by_xpath(TreeAreaLocators.server_group_node("Servers")) + ActionChains(self.driver).context_click(server_group_node).perform() + ActionChains(self.driver).move_to_element(self.find_by_xpath( + TreeAreaLocators.context_menu_element('Create'))).perform() + ActionChains(self.driver).move_to_element(self.find_by_xpath( + TreeAreaLocators.context_menu_element('Server...'))) \ + .click().perform() WebDriverWait(self.driver, 5).until(EC.visibility_of_element_located( - (By.XPATH, "//div[text()='Create - Server']"))) + (By.XPATH, PropertyDialogueLocators.server_dialogue_title))) # After server dialogue opens - self.fill_input_by_field_name("name", server_config['name'], - loose_focus=True) - self.find_by_partial_link_text("Connection").click() - self.fill_input_by_field_name("host", server_config['host']) - self.fill_input_by_field_name("port", server_config['port']) - self.fill_input_by_field_name("username", server_config['username']) - self.fill_input_by_field_name("password", server_config['db_password']) - WebDriverWait(self.driver, 10).until(EC.element_to_be_clickable( - (By.CSS_SELECTOR, "button[type='save'].btn.btn-primary"))) - self.find_by_css_selector("button[type='save'].btn.btn-primary").\ - click() + self.fill_input_by_field_name( + "name", server_config['name'], input_keys=True) + self.find_by_xpath( + PropertyDialogueLocators.server_connection_tab).click() + self.fill_input_by_field_name( + "host", server_config['host'], input_keys=True) + self.fill_input_by_field_name( + "port", server_config['port'], input_keys=True) + self.fill_input_by_field_name( + "username", server_config['username'], input_keys=True) + self.fill_input_by_field_name( + "password", server_config['db_password'], input_keys=True) - server_tree_xpath = \ - "//*[@id='tree']//*[.='" + server_config['name'] + "']" + save_btn = WebDriverWait(self.driver, 5).until( + EC.element_to_be_clickable( + (By.XPATH, PropertyDialogueLocators.server_tab_save))) + save_btn.click() + + server_tree_xpath = TreeAreaLocators.server_node(server_config['name']) try: WebDriverWait(self.driver, 10).until( EC.visibility_of_element_located( (By.XPATH, server_tree_xpath))) except TimeoutException: - self.toggle_open_servers_group() + self.expand_server_group_node("Server") WebDriverWait(self.driver, 10).until( EC.visibility_of_element_located( (By.XPATH, server_tree_xpath))) def open_query_tool(self): - self.driver.find_element_by_link_text("Tools").click() - tools_menu = self.driver.find_element_by_id('mnu_tools') + self.driver.find_element(By.LINK_TEXT, "Tools").click() + tools_menu = self.driver.find_element(By.ID, 'mnu_tools') - query_tool = tools_menu.find_element_by_id('query_tool') + query_tool = tools_menu.find_element(By.ID, 'query_tool') self.enable_menu_item(query_tool, 10) self.find_by_partial_link_text("Query Tool").click() + self.wait_for_element_to_be_visible( + self.driver, "//div[@id='btn-conn-status']", 5) + def open_view_data(self, table_name): self.driver.find_element_by_link_text("Object").click() ActionChains( @@ -259,6 +261,7 @@ class PgadminPage: break else: retry -= 1 + if option == 'auto_commit': update_execute_option_setting( QueryToolLocators.btn_auto_commit_check_status, @@ -303,29 +306,33 @@ class PgadminPage: QueryToolLocators.btn_auto_rollback) def close_data_grid(self): - self.driver.switch_to_default_content() + self.driver.switch_to.default_content() xpath = "//*[@id='dockerContainer']/div/div[3]/div/div[2]/div[1]" self.click_element(self.find_by_xpath(xpath)) def remove_server(self, server_config): self.driver.switch_to.default_content() - server_to_remove = self.find_by_xpath( - "//*[@id='tree']//*[.='" + server_config['name'] + - "' and @class='aciTreeItem']") - self.driver.execute_script( - self.js_executor_scrollintoview_arg, server_to_remove) - self.click_element(server_to_remove) - object_menu_item = self.find_by_partial_link_text("Object") - self.click_element(object_menu_item) - delete_menu_item = self.find_by_partial_link_text("Remove Server") - self.click_element(delete_menu_item) - self.click_modal('Yes') - time.sleep(1) + server_to_remove = self.check_if_element_exists_with_scroll( + TreeAreaLocators.server_node(server_config['name'])) + if server_to_remove: + self.driver.execute_script( + self.js_executor_scrollintoview_arg, server_to_remove) + self.click_element(server_to_remove) + object_menu_item = self.find_by_partial_link_text("Object") + self.click_element(object_menu_item) + delete_menu_item = self.find_by_partial_link_text("Remove Server") + self.click_element(delete_menu_item) + self.click_modal('Yes') + time.sleep(1) + else: + print("%s Server is not removed", server_config['name'], + file=sys.stderr) + # TODO - Not used to be deleted def select_tree_item(self, tree_item_text): item = self.find_by_xpath( - "//*[@id='tree']//*[contains(text(), '" + tree_item_text + "')]" - "/parent::span[@class='aciTreeItem']") + "//*[@id='tree']//*[contains(text(), '" + tree_item_text + + "')]/parent::span[@class='aciTreeItem']") self.driver.execute_script(self.js_executor_scrollintoview_arg, item) # unexpected exception like element overlapping, click attempts more # than one time @@ -340,6 +347,7 @@ class PgadminPage: if attempts == 0: raise e + # TODO - Not used to be deleted def click_a_tree_node(self, element_name, list_of_element): """It will click a tree node eg. server, schema, table name etc will take server name and list of element where this node lies""" @@ -368,333 +376,423 @@ class PgadminPage: "click_a_tree_node seems empty") return operation_status - def toggle_open_servers_group(self): - """This will open Servers group to display underlying nodes""" - is_expanded = False - self.wait_for_spinner_to_disappear() - if self.check_if_element_exist_by_xpath( - TreeAreaLocators.server_group_node): - if self.get_expansion_status_of_node( - TreeAreaLocators.server_group_node_exp_status): - is_expanded = True - else: - webdriver.ActionChains(self.driver).double_click( - self.find_by_xpath( - TreeAreaLocators. - server_group_node)).perform() - if self.check_if_element_exist_by_xpath( - TreeAreaLocators.server_group_sub_nodes): - is_expanded = True - else: - print( - "(toggle_open_servers_group)The Server Group " - "node is clicked to expand but it is not expanded", - file=sys.stderr) - else: - print("The Server Group node is not visible", - file=sys.stderr) - return is_expanded - - def expand_server_node(self, server_name, server_password): - """will expand a particular server node""" - server_node_expansion_status = False - if self.toggle_open_servers_group(): - if self.wait_for_elements_to_appear( - self.driver, - TreeAreaLocators.server_group_sub_nodes): - subnodes_of_servers = self.find_by_xpath_list( - TreeAreaLocators.server_group_sub_nodes) - subnodes_of_servers_expansion_status = \ - self.find_by_xpath_list( - TreeAreaLocators. - server_group_sub_nodes_exp_status) - index_of_server_node = self.get_index_of_element( - subnodes_of_servers, server_name) - - server_node_expansion_status = self.click_expand_server_node( - subnodes_of_servers_expansion_status, - index_of_server_node, - subnodes_of_servers, - server_name, - server_password) - else: - print( - "(expand_server_node) The Servers node is" - " not expanded", - file=sys.stderr) - return server_node_expansion_status - - def click_expand_server_node(self, subnodes_of_servers_expansion_status, - index_of_server_node, subnodes_of_servers, - server_name, server_password): + def click_to_expand_tree_node(self, tree_node_web_element, + tree_node_exp_check_xpath): """ - Method actually clicks on server node to expand - :param subnodes_of_servers_expansion_status: - :param index_of_server_node: - :param subnodes_of_servers: + Method clicks passed webelement to expand specified tree node + :param tree_node_web_element: + :param tree_node_exp_check_xpath: + :return: True is tree_node_exp_check_xpath present in DOM else false + """ + webdriver.ActionChains(self.driver).double_click( + tree_node_web_element).perform() + if self.check_if_element_exist_by_xpath(tree_node_exp_check_xpath): + return True + else: + return False + + def expand_server_group_node(self, server_group_name): + """ + Expands specified server group + :param server_group_name: + :return: True is server group is expanded else false + """ + server_group_expanded = False + self.wait_for_spinner_to_disappear() + server_group_node_xpath = \ + TreeAreaLocators.server_group_node(server_group_name) + server_group_node_exp_status_xpath = \ + TreeAreaLocators.server_group_node_exp_status(server_group_name) + server_group_node = self.check_if_element_exists_with_scroll( + server_group_node_xpath) + + if server_group_node: + if self.check_if_element_exist_by_xpath( + server_group_node_exp_status_xpath, 1): + server_group_expanded = True + else: + server_group_expanded = self.click_to_expand_tree_node( + server_group_node, server_group_node_exp_status_xpath) + if server_group_expanded: + server_group_expanded = True + else: + print("(expand_server_group_node)The Server Group node is " + "clicked to expand but it is not expanded", + file=sys.stderr) + else: + print("(expand_server_group_node)The Server Group node not found", + file=sys.stderr) + return server_group_expanded + + def expand_server_node(self, server_group_name, server_name, + server_password): + """ + Method expands specified server node + :param server_group_name: containing server :param server_name: :param server_password: + :return: true if server node is expnaded else false + """ + server_expanded = False + server_node_xpath = TreeAreaLocators.server_node(server_name) + server_node_exp_status_xpath = \ + TreeAreaLocators.server_node_exp_status(server_name) + if self.expand_server_group_node(server_group_name): + server_node = \ + self.check_if_element_exists_with_scroll(server_node_xpath) + if server_node: + self.driver.execute_script( + self.js_executor_scrollintoview_arg, server_node) + if self.check_if_element_exist_by_xpath( + server_node_exp_status_xpath, 1): + server_expanded = True + else: + server_expanded = self.click_expand_server_node( + server_name, server_password, server_node) + if not server_expanded: + print("(expand_server_node)The Server node is not " + "expnaded", file=sys.stderr) + else: + print("(expand_server_node)The Server node not found", + file=sys.stderr) + else: + print("The server group node is not expanded", file=sys.stderr) + return server_expanded + + def click_expand_server_node(self, server_name, server_password, + server_node): + """ + Method actually clicks on server node to expand + :param server_name: + :param server_password: + :param server_node: :return: True is click action is successful & server node expanded """ server_node_expansion_status = False - if not self.check_server_is_connected( - index_of_server_node): - if self.click_and_connect_server( - subnodes_of_servers[index_of_server_node], - server_password): + if self.check_server_is_connected(server_name): + if self.check_if_element_exist_by_xpath( + TreeAreaLocators.server_node_exp_status(server_name), 1): server_node_expansion_status = True else: - print( - "(expand_server_node)The server node is " - "not expanded", - file=sys.stderr) - else: - if not self.get_expansion_status_of_node_element( - subnodes_of_servers_expansion_status[ - index_of_server_node]): + # if server is connected but not expanded webdriver.ActionChains(self.driver).double_click( - subnodes_of_servers[ - index_of_server_node]).perform() - if self.wait_for_elements_to_appear( - self.driver, TreeAreaLocators. - sub_nodes_of_a_server_node(server_name), - 30): + server_node).perform() + if self.check_if_element_exist_by_xpath( + TreeAreaLocators.server_node_exp_status(server_name)): server_node_expansion_status = True - else: + else: + if self.click_and_connect_server(server_name, server_password): server_node_expansion_status = True + else: + print("(expand_server_node)The server node is not expanded", + file=sys.stderr) return server_node_expansion_status - def expand_databases_node(self, server_name, server_password): - """will expand databases node under server node""" - databases_node_expanded = False - if self.expand_server_node(server_name, server_password): - if self.wait_for_elements_to_appear( - self.driver, - TreeAreaLocators.sub_nodes_of_a_server_node(server_name)): - subnodes_of_server_node = self.find_by_xpath_list( - TreeAreaLocators.sub_nodes_of_a_server_node(server_name)) - subnode_of_server_node_exp_status = self.find_by_xpath_list( - TreeAreaLocators.sub_nodes_of_a_server_node_exp_status( - server_name)) - index_of_databases_node = self.get_index_of_element( - subnodes_of_server_node, - "Databases") - time.sleep(2) - expansion_status = self.get_expansion_status_of_node_element( - subnode_of_server_node_exp_status[index_of_databases_node]) - if not expansion_status: - databases_node_expanded = \ - self.click_to_expand_databases_node( - subnodes_of_server_node, - index_of_databases_node, - server_name) - else: - databases_node_expanded = True - else: - print("The server/previous nodes not expanded", - file=sys.stderr) - return databases_node_expanded - - def click_to_expand_databases_node(self, subnodes_of_server_node, - index_of_databases_node, server_name): + def check_server_is_connected(self, server_name): """ - Method clicks on databases node of specified server to expand - :param subnodes_of_server_node: - :param index_of_databases_node: + This will check connected status of a server" :param server_name: - :return: True if database node click is successful & expanded + :return: true if server is connected """ - retry = 5 - databases_node_expanded = False - while retry > 0: - webdriver.ActionChains(self.driver).double_click( - subnodes_of_server_node[ - index_of_databases_node].find_element_by_xpath( - ".//*[@class='aciTreeItem']") - ).perform() - if self.wait_for_elements_to_appear( - self.driver, TreeAreaLocators. - sub_nodes_of_databases_node(server_name), 3): - databases_node_expanded = True - break - else: - retry -= 1 - return databases_node_expanded - - def click_to_expand_database_node(self, sub_nodes_of_databases_node, - index_of_required_db_node, - name_of_database): - """ - Method clicks on specified database name from expanded databases node - of server. - :param sub_nodes_of_databases_node: - :param index_of_required_db_node: - :param name_of_database: - :return: True if particular database click is successful & expanded - """ - retry = 5 - db_node_expanded_status = False - self.driver.execute_script(self.js_executor_scrollintoview_arg, - sub_nodes_of_databases_node[ - index_of_required_db_node]) - 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): - try: - self.click_modal('OK') - except Exception: - pass - retry -= 1 - else: - break - if self.wait_for_elements_to_appear( - self.driver, TreeAreaLocators. - sub_nodes_of_database_node( - name_of_database)): - db_node_expanded_status = True - return db_node_expanded_status - - def expand_database_node(self, server_name, server_password, - name_of_database): - """will expand database node under databases node""" - db_node_expanded_status = False - 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)) - index_of_required_db_node = self.get_index_of_element( - sub_nodes_of_databases_node, - name_of_database) - expansion_status = self.get_expansion_status_of_node_element( - self.find_by_xpath_list( - TreeAreaLocators. - sub_nodes_of_databases_node_exp_status( - server_name))[ - index_of_required_db_node]) - if not expansion_status: - db_node_expanded_status = self.click_to_expand_database_node( - sub_nodes_of_databases_node, index_of_required_db_node, - name_of_database) - else: - db_node_expanded_status = True - else: - print("The databases/previous nodes not expanded", + server_connected = False + try: + server_connection_status_element = self.find_by_xpath( + TreeAreaLocators.server_connection_status_element(server_name)) + server_class = server_connection_status_element.get_attribute( + 'class') + if server_class == 'icon-pg' or server_class == 'icon-ppas': + server_connected = True + except Exception as e: + print("There is some exception thrown in the function " + "check_server_is_connected and is: " + str(e), file=sys.stderr) - return db_node_expanded_status + return server_connected - def toggle_open_schemas_node(self, server_name, server_password, - name_of_database): - """will expand schemas node under a db node""" - expansion_status = False - if self.expand_database_node(server_name, server_password, - name_of_database): - sub_nodes_db_node = self.find_by_xpath_list( - TreeAreaLocators.sub_nodes_of_database_node( - name_of_database)) - index_of_schemas_node = self.get_index_of_element( - sub_nodes_db_node, "Schemas") - expansion_status = self.get_expansion_status_of_node_element( - self.find_by_xpath_list( - TreeAreaLocators.sub_nodes_of_database_node_exp_status( - name_of_database))[ - index_of_schemas_node]) - if not expansion_status: + def click_and_connect_server(self, server_name, password): + """ + Method will connect to server with password + :param server_name: + :param password: + :return: + """ + server_connection_status = False + try: + server_node_ele = self.find_by_xpath( + TreeAreaLocators.server_node(server_name)) + webdriver.ActionChains(self.driver). \ + double_click(server_node_ele).perform() + if self.check_if_element_exist_by_xpath( + ConnectToServerDiv.ok_button): + field = self.find_by_xpath( + ConnectToServerDiv.password_field) + self.fill_input(field, password) + self.find_by_xpath(ConnectToServerDiv.ok_button).click() + self.wait_for_element_to_disappear( + lambda driver: driver.find_element_by_xpath( + ConnectToServerDiv.ok_button)) + if self.check_if_element_exist_by_xpath( + ConnectToServerDiv.error_message, 2): + print( + "While entering password in click_and_connect_server " + "function, error is occurred : " + str( + self.find_by_xpath( + ConnectToServerDiv.error_message).text), + file=sys.stderr) + else: + server_connection_status = True + except Exception as e: + print( + "There is some exception thrown click_and_connect_server " + "and is: " + str( + e), file=sys.stderr) + return server_connection_status + + def expand_databases_node(self, server_group_name, server_name, + server_password): + """ + Method expands Databases node of specfied server + :param server_group_name: + :param server_name: + :param server_password: + :return: + """ + return self.expand_server_child_node(server_group_name, server_name, + server_password, "Databases") + + def expand_server_child_node(self, server_group_name, server_name, + server_password, server_child_node_name): + """ + Method expands specified server node's child + :param server_group_name: + :param server_name: + :param server_password: + :param server_child_node_name: to be expanded + :return: true is child node is expanded else false + """ + server_child_expanded = False + server_child_node_xpath = TreeAreaLocators. \ + server_child_node(server_name, server_child_node_name) + server_child_node_exp_status_xpath = TreeAreaLocators. \ + server_child_node_exp_status(server_name, server_child_node_name) + + if self.expand_server_node(server_group_name, server_name, + server_password): + if self.check_if_element_exist_by_xpath( + server_child_node_exp_status_xpath, 1): + server_child_expanded = True + else: + child_node_ele = self.check_if_element_exists_with_scroll( + server_child_node_xpath) + server_child_expanded = self.click_to_expand_tree_node( + child_node_ele, server_child_node_exp_status_xpath) + if not server_child_expanded: + print("Child not is not expanded after clickng ", + file=sys.stderr) + else: + print("The server/previous nodes not expanded", file=sys.stderr) + return server_child_expanded + + def expand_database_node(self, server_group_name, server_name, + server_password, database_name): + """ + will expand database node under databases node" + :param server_group_name: + :param server_name: + :param server_password: + :param database_name: + :return: + """ + database_expanded = False + database_node_xpath = TreeAreaLocators.database_node(database_name) + database_node_exp_xpath = \ + TreeAreaLocators.database_node_exp_status(database_name) + + if self.expand_databases_node( + server_group_name, server_name, server_password): + database_node = \ + self.check_if_element_exists_with_scroll(database_node_xpath) + if database_node: self.driver.execute_script( - self.js_executor_scrollintoview_arg, - sub_nodes_db_node[index_of_schemas_node]) - webdriver.ActionChains(self.driver).double_click( - sub_nodes_db_node[index_of_schemas_node]).perform() - if self.wait_for_elements_to_appear( - self.driver, TreeAreaLocators. - sub_nodes_of_schemas_node(name_of_database)): - expansion_status = True + self.js_executor_scrollintoview_arg, database_node) + if self.check_if_element_exist_by_xpath( + database_node_exp_xpath, 1): + database_expanded = True + else: + database_expanded = self.click_to_expand_tree_node( + database_node, database_node_exp_xpath) else: - expansion_status = True + print("Database node not found - ", file=sys.stderr) else: - print( - "(expand_schemas_node) database/previous nodes " - "are not expanded", - file=sys.stderr) - return expansion_status + print("The databases/previous nodes not expanded", file=sys.stderr) + return database_expanded - def toggle_open_schema_node( - self, server_name, server_password, - name_of_database, name_of_schema_node): - """will expand schema node under schemas node""" - expansion_status = False - if self.toggle_open_schemas_node( - server_name, server_password, name_of_database): - sub_nodes_schemas_node = self.find_by_xpath_list( - TreeAreaLocators.sub_nodes_of_schemas_node( - name_of_database)) - index_of_schema_node = self.get_index_of_element( - sub_nodes_schemas_node, - name_of_schema_node) - expansion_status = self.get_expansion_status_of_node_element( - self.find_by_xpath_list( - TreeAreaLocators.sub_nodes_of_schemas_node_exp_status( - name_of_database))[ - index_of_schema_node]) - if not expansion_status: + # TODO - We might need this method + # def click_to_expand_database_node(self, database_name, database_node): + # """ + # Method clicks on specified database name from expanded databases node + # of server. + # :param sub_nodes_of_databases_node: + # :param index_of_required_db_node: + # :param name_of_database: + # :return: True if particular database click is successful & expanded + # """ + # database_expanded = False + # if self.check_if_element_exist_by_xpath( + # TreeAreaLocators.database_node_exp_status(database_name), 2): + # database_expanded = True + # else: + # # TODO - This is bug 6962 + # webdriver.ActionChains(self.driver).click(database_node).perform() + # if self.check_if_element_exist_by_xpath( + # TreeAreaLocators.database_node_exp_status(database_name)): + # database_expanded = True + # print("click_to_expand_database_node> db_node_expanded_status - ", + # database_expanded) + # return database_expanded + # + + def expand_database_child_node(self, server_group_name, server_name, + server_password, database_name, + database_child_node_name): + """ + Method expands specified database's child + :param server_group_name: + :param server_name: + :param server_password: + :param database_name: + :param database_child_node_name: + :return: + """ + database_child_expanded = False + database_child_node_xpath = \ + TreeAreaLocators.database_child_node( + database_name, database_child_node_name) + database_child_node_exp_status_xpath = \ + TreeAreaLocators.database_child_node_exp_status( + database_name, database_child_node_name) + + if self.expand_database_node(server_group_name, server_name, + server_password, database_name): + child_node_ele = self.check_if_element_exists_with_scroll( + database_child_node_xpath) + if child_node_ele: + if self.check_if_element_exist_by_xpath( + database_child_node_exp_status_xpath, 1): + database_child_expanded = True + else: + database_child_expanded = self.click_to_expand_tree_node( + child_node_ele, database_child_node_exp_status_xpath) + else: + print("Node not found - ", database_child_node_name, + file=sys.stderr) + else: + print("The database/previous nodes not expanded", file=sys.stderr) + return database_child_expanded + + def expand_schemas_node(self, server_group_name, server_name, + server_password, database_name): + """ + Method expands Schemas node under specified server & database + :param server_group_name: + :param server_name: + :param server_password: + :param database_name: + :return: + """ + return self.expand_database_child_node(server_group_name, server_name, + server_password, database_name, + "Schemas") + + def expand_schema_node(self, server_group_name, server_name, + server_password, database_name, schema_name): + """ + Method expands schema node + :param server_group_name: + :param server_name: + :param server_password: + :param database_name: + :param schema_name: + :return: + """ + schema_expanded = False + schema_node_xpath = TreeAreaLocators.schema_node(schema_name) + schema_node_exp_xpath = TreeAreaLocators.schema_node_exp_status( + schema_name) + + if self.expand_schemas_node(server_group_name, server_name, + server_password, database_name): + schema_node = self.check_if_element_exists_with_scroll( + schema_node_xpath) + if schema_node: self.driver.execute_script( - self.js_executor_scrollintoview_arg, - sub_nodes_schemas_node[index_of_schema_node]) - webdriver.ActionChains(self.driver).double_click( - sub_nodes_schemas_node[index_of_schema_node]).perform() - if self.wait_for_elements_to_appear( - self.driver, TreeAreaLocators. - sub_nodes_of_schema_node(name_of_database)): - expansion_status = True + self.js_executor_scrollintoview_arg, schema_node) + if self.check_if_element_exist_by_xpath( + schema_node_exp_xpath, 1): + schema_expanded = True + else: + schema_expanded = self.click_to_expand_tree_node( + schema_node, schema_node_exp_xpath) else: - expansion_status = True + print("Schema node not found - ", file=sys.stderr) else: - print( - "(expand_schema_node) schema/previous nodes are" - " not expanded", - file=sys.stderr) - return expansion_status + print("The schemas/previous nodes not expanded", file=sys.stderr) + return schema_expanded - def toggle_open_tables_node( - self, server_name, server_password, - name_of_database, name_of_schema_node): - """will expand tables node under schema node""" - node_expanded_successfully = False - if self.toggle_open_schema_node( - server_name, server_password, name_of_database, - name_of_schema_node): - sub_nodes_of_schema_node = self.find_by_xpath_list( - TreeAreaLocators.sub_nodes_of_schema_node( - name_of_database)) - sub_nodes_of_schema_node_exp_status = self.find_by_xpath_list( - TreeAreaLocators.sub_nodes_of_schema_node_exp_status( - name_of_database)) - index_of_tables_node = self.get_index_of_element( - sub_nodes_of_schema_node, "Tables") - expansion_status = self.get_expansion_status_of_node_element( - sub_nodes_of_schema_node_exp_status[index_of_tables_node]) - if not expansion_status: - self.driver.execute_script(self.js_executor_scrollintoview_arg, - sub_nodes_of_schema_node[ - index_of_tables_node]) - webdriver.ActionChains(self.driver).double_click( - sub_nodes_of_schema_node[ - index_of_tables_node]).perform() - if self.wait_for_elements_to_appear( - self.driver, TreeAreaLocators. - sub_nodes_of_tables_node): - node_expanded_successfully = True + def expand_tables_node(self, server_group, server_name, server_password, + database_name, schema_name): + """ + Method expands tables nodes under schema + :param server_group: + :param server_name: + :param server_password: + :param database_name: + :param schema_name: + :return: + """ + return self.expand_schema_child_node(server_group, server_name, + server_password, database_name, + schema_name, "Tables") + + def expand_schema_child_node(self, server_group_name, server_name, + server_password, database_name, schema_name, + schema_child_node_name): + """ + Expands specified child node of schema + :param server_group_name: + :param server_name: + :param server_password: + :param database_name: + :param schema_name: + :param schema_child_node_name: + :return: + """ + schema_child_expanded = False + schema_child_node_xpath = TreeAreaLocators. \ + schema_child_node(schema_name, schema_child_node_name) + schema_child_node_exp_status_check_xpath = TreeAreaLocators. \ + schema_child_node_exp_status(schema_name, schema_child_node_name) + + if self.expand_schema_node(server_group_name, server_name, + server_password, database_name, + schema_name): + child_node_ele = self.check_if_element_exists_with_scroll( + schema_child_node_xpath) + if child_node_ele: + if self.check_if_element_exist_by_xpath( + schema_child_node_exp_status_check_xpath, 1): + schema_child_expanded = True + else: + schema_child_expanded = self.click_to_expand_tree_node( + child_node_ele, + schema_child_node_exp_status_check_xpath) else: - node_expanded_successfully = True + print("%s node not found - ", schema_child_node_name, + file=sys.stderr) else: - print( - "(expand_tables_node) schema/previous nodes " - "are not expanded", - file=sys.stderr) - return node_expanded_successfully + print("The schema/previous nodes not expanded", file=sys.stderr) + return schema_child_expanded + # TODO Not used any where to be removed def toggle_open_function_node(self): """The function will be used for opening Functions node only""" node_expanded = False @@ -749,76 +847,7 @@ class PgadminPage: else: node_expanded = True - def check_server_is_connected(self, index_of_server): - """This will check connected status of a server, as connection - status is contained either in span or div element so checking it""" - server_connected = False - try: - connection_status_elements = self.find_by_xpath_list( - TreeAreaLocators.server_group_sub_nodes_connected_status) - span_elements = connection_status_elements[ - index_of_server].find_elements_by_tag_name("span") - div_elements = connection_status_elements[ - index_of_server].find_elements_by_tag_name("div") - - span_value_of_class_att = "" - div_value_of_class_att = "" - - if len(span_elements) > 0: - span_value_of_class_att = \ - span_elements[0].get_attribute('class') - if len(div_elements) > 0: - div_value_of_class_att = \ - div_elements[0].get_attribute('class') - if (("aciTreeIcon icon-pg" in span_value_of_class_att or - "aciTreeIcon icon-pg" in div_value_of_class_att or - "aciTreeIcon icon-ppas" in - span_value_of_class_att or - "aciTreeIcon icon-ppas" in div_value_of_class_att) and - ("aciTreeIcon icon-server-not-connected" not in - span_value_of_class_att or - "aciTreeIcon icon-server-not-connected" not in - div_value_of_class_att)): - server_connected = True - except Exception as e: - print("There is some exception thrown in the function " - "check_server_is_connected and is: " + str(e), - file=sys.stderr) - return server_connected - - def click_and_connect_server(self, server_element, password): - """will connect a server node, will provide the password in the - respective window""" - server_connection_status = False - try: - webdriver.ActionChains(self.driver).double_click( - server_element).perform() - if self.check_if_element_exist_by_xpath( - ConnectToServerDiv.ok_button): - field = self.find_by_xpath( - ConnectToServerDiv.password_field) - self.fill_input(field, password) - self.find_by_xpath(ConnectToServerDiv.ok_button).click() - self.wait_for_element_to_disappear( - lambda driver: driver.find_element_by_xpath( - ConnectToServerDiv.ok_button)) - if self.check_if_element_exist_by_xpath( - ConnectToServerDiv.error_message, 2): - print( - "While entering password in click_and_connect_server " - "function, error is occurred : " + str( - self.find_by_xpath( - ConnectToServerDiv.error_message).text), - file=sys.stderr) - else: - server_connection_status = True - except Exception as e: - print( - "There is some exception thrown click_and_connect_server " - "and is: " + str( - e), file=sys.stderr) - return server_connection_status - + # TODO Not used any where to be removed def get_expansion_status_of_node(self, xpath_node): """get the expansion status for a node through xpath""" node_is_expanded = False @@ -827,6 +856,7 @@ class PgadminPage: node_is_expanded = True return node_is_expanded + # TODO Not used any where to be removed def get_expansion_status_of_node_element(self, element): """get the expansion status for an element""" node_is_expanded = False @@ -840,6 +870,7 @@ class PgadminPage: e), file=sys.stderr) return node_is_expanded + # TODO Not used any where to be removed def toggle_open_tree_item(self, tree_item_text): # 'sleep' here helps in cases where underlying nodes are auto opened. # Otherwise, encountered situations where False value is returned @@ -868,6 +899,7 @@ class PgadminPage: except TimeoutException: retry -= 1 + # TODO Not used any where to be removed def toggle_open_server(self, tree_item_text): def check_for_password_dialog_or_tree_open(driver): try: @@ -896,17 +928,17 @@ class PgadminPage: def find_by_xpath(self, xpath): return self.wait_for_element( - lambda driver: driver.find_element_by_xpath(xpath) + lambda driver: driver.find_element(By.XPATH, xpath) ) def find_by_id(self, element_id): return self.wait_for_element( - lambda driver: driver.find_element_by_id(element_id) + lambda driver: driver.find_element(By.ID, element_id) ) def find_by_css_selector(self, css_selector): return self.wait_for_element( - lambda driver: driver.find_element_by_css_selector(css_selector) + lambda driver: driver.find_element(By.CSS_SELECTOR, css_selector) ) def find_by_partial_link_text(self, link_text): @@ -1005,7 +1037,7 @@ class PgadminPage: def find_codemirror(driver): try: driver.switch_to.default_content() - driver.switch_to_frame( + driver.switch_to.frame( driver.find_element_by_tag_name("iframe")) element = driver.find_element_by_css_selector( "#output-panel .CodeMirror") @@ -1013,6 +1045,7 @@ class PgadminPage: return element except (NoSuchElementException, WebDriverException): return False + time.sleep(1) self.wait_for_query_tool_loading_indicator_to_disappear(12) @@ -1133,7 +1166,7 @@ class PgadminPage: def wait_for_spinner_to_disappear(self): def spinner_has_disappeared(driver): try: - driver.find_element_by_id("pg-spinner") + driver.find_element(By.ID, "pg-spinner") return False except NoSuchElementException: return True @@ -1145,9 +1178,9 @@ class PgadminPage: try: # Refer the status message as spinner appears only on the # the data output panel - spinner = driver.find_element_by_css_selector( - ".sql-editor .sql-editor-busy-text-status" - ) + spinner = driver.find_element( + By.CSS_SELECTOR, + ".sql-editor .sql-editor-busy-text-status") return "d-none" in spinner.get_attribute("class") except NoSuchElementException: # wait for loading indicator disappear animation to complete. @@ -1195,8 +1228,8 @@ class PgadminPage: def element_if_it_exists(driver): try: element = find_method_with_args(driver) - if len(element) > 0 and element[0].is_displayed() and element[ - 0].is_enabled(): + if len(element) > 0 and element[0].is_displayed() and \ + element[0].is_enabled(): return element except NoSuchElementException: return False @@ -1209,18 +1242,66 @@ class PgadminPage: elements_located_status = False try: if WebDriverWait(driver, time_value).until( - EC.visibility_of_any_elements_located(( - By.XPATH, locator))): + EC.visibility_of_any_elements_located(( + By.XPATH, locator))): elements_located_status = True except Exception: pass return elements_located_status + def check_if_element_exists_with_scroll(self, xpath): + f_scroll, r_scroll = 111, 111 + while f_scroll > 0 or r_scroll > 0: + try: + ele = WebDriverWait(self.driver, 1, 0.01).until( + lambda d: d.find_element(By.XPATH, xpath)) + f_scroll, r_scroll = 0, 0 + return ele + except (TimeoutException, NoSuchElementException) as e: + tree_height = int((self.driver.find_element( + By.XPATH, "//div[@class='file-tree']/div[1]/div/div"). + value_of_css_property('height')).split("px")[0]) + + if f_scroll == 111 and r_scroll == 111: + window_size = int(self.driver.get_window_size()["height"]) + f_scroll = r_scroll = (tree_height / window_size + 1) + + if f_scroll > 0: + bottom_ele = self.driver.find_element( + By.XPATH, + "//div[@id='tree']/div/div/div/div/div[last()]") + bottom_ele_location = int( + bottom_ele.value_of_css_property('top').split("px")[0]) + + if tree_height - bottom_ele_location < 25: + f_scroll = 0 + else: + self.driver.execute_script( + self.js_executor_scrollintoview_arg, bottom_ele) + f_scroll -= 1 + elif r_scroll > 0: + top_el = self.driver.find_element( + By.XPATH, + "//div[@id='tree']/div/div/div/div/div[1]") + top_el_location = int( + top_el.value_of_css_property('top').split("px")[0]) + + if (tree_height - top_el_location) == tree_height: + r_scroll = 0 + else: + webdriver.ActionChains(self.driver).move_to_element( + top_el).perform() + r_scroll -= 1 + else: + print("check_if_element_exists_with_scroll > Element NOT found") + return False + def find_by_xpath_list(self, xpath): """This will find out list of elements through a single xpath""" return self.wait_for_elements( - lambda driver: driver.find_elements_by_xpath(xpath)) + lambda driver: driver.find_elements(By.XPATH, xpath)) + # TODO Not used any where to be removed def get_index_of_element(self, element_list, target_string): """it will return index of an element from provided element list""" index_of_required_server = -1 diff --git a/web/regression/feature_utils/tree_area_locators.py b/web/regression/feature_utils/tree_area_locators.py index d6968e77b..f0e8f0b39 100644 --- a/web/regression/feature_utils/tree_area_locators.py +++ b/web/regression/feature_utils/tree_area_locators.py @@ -11,126 +11,260 @@ class TreeAreaLocators(): """This will contains element locators for tree area, will also contain parametrized xpath where applicable""" - server_group_node = \ - "//div[@id='tree']//span[@class='aciTreeItem']" \ - "/span[(@class='aciTreeText') and starts-with(text(),'Servers ') or " \ - "starts-with(text(), 'Servers')]" - - server_group_node_exp_status = "//div[div[span[span[" \ - "(@class='aciTreeText') and " \ - "(text()='Servers ' or " \ - "text()='Servers')]]]]" - - server_group_sub_nodes = \ - "//div[div[span[span[contains(text(),'Servers')]]]]/" \ - "following-sibling::ul/li/div/div/div/span[2]/" \ - "span[@class='aciTreeText']" - - server_group_sub_nodes_exp_status = \ - "//div[div[span[span[contains(text(),'Servers')]]]]" \ - "/following-sibling::ul/li/div" - - server_group_sub_nodes_connected_status = \ - "//div[div[span[span[contains(text(), 'Servers')]]]]/" \ - "following-sibling::ul/li/div/div/div/span[2]" - - specified_tree_node = \ - "//div[@id='tree']//span[@class='aciTreeItem']/" \ - "span[(@class='aciTreeText') and text()='{}']" - - specified_tree_node_exp_status = \ - "//div[@id='tree']//span[@class='aciTreeItem']/" \ - "span[(@class='aciTreeText') and text()='{}']" \ - "//ancestor::*[@class='aciTreeLine']" - - sub_nodes_of_tables_node = \ - "//div[div[div[div[div[div[div[div[span[span[" \ - "contains(text(),'Tables')]]]]]]]]]]/" \ - "following-sibling::ul/li/div//div/span[2]/span[2]" - - sub_nodes_of_functions_node = \ - "//div[div[div[div[div[div[div[div[span[span[" \ - "contains(text(),'Functions')]]]]]]]]]]/" \ - "following-sibling::ul/li/div//div/span[2]/span[2]" - - sub_nodes_of_login_group_node = \ - "//div[div[div[span[span[contains(text(),'Login/Group Roles')]]]]]" \ - "/following::ul/li/div[@class='aciTreeLine']" + # Server Group Node + @staticmethod + def server_group_node(server_group_name): + return "//span[starts-with(text(),'%s')]" % server_group_name @staticmethod - def sub_nodes_of_a_server_node(server_name): - xpath = "//div[div[div[span[span[contains(text(),'%s')]]]]]/" \ - "following-sibling::ul/li/div[@class='aciTreeLine']" % \ - server_name - return xpath + def server_group_node_exp_status(server_group_name): + return "//i[@class='directory-toggle open']/following-sibling::" \ + "span//span[starts-with(text(),'%s')]" % server_group_name + + # Server Node + @staticmethod + def server_node(server_name): + return "//div[@id='tree']//span[starts-with(text(),'%s')]" \ + % server_name @staticmethod - def sub_nodes_of_a_server_node_exp_status(server_name): - xpath = "//div[div[div[span[span[contains(text(),'%s')]]]]]/" \ - "following-sibling::ul/li/div" % server_name - return xpath + def server_node_exp_status(server_name): + return "//i[@class='directory-toggle open']/following-sibling::" \ + "span//span[starts-with(text(),'%s')]" % server_name + + # Server Connection + @staticmethod + def server_connection_status_element(server_name): + return "//div[@id='tree']//span[starts-with(text(),'%s')]/" \ + "preceding-sibling::i" % server_name + + # Databases Node + @staticmethod + def databases_node(server_name): + return "//div[div[span[span[starts-with(text(),'%s')]]]]/" \ + "following-sibling::div//span[text()='Databases']" % server_name @staticmethod - def databases_node_of_a_server_node(server_name): - xpath = "//div[div[div[span[span[contains(text(),'%s')]]]]]/" \ - "following-sibling::ul/li/div/div/div/div/span[2]/span[2 " \ - "and text()='Databases ']" % server_name - return xpath + def databases_node_exp_status(server_name): + return "//div[div[span[span[starts-with(text(),'%s')]]]]/" \ + "following-sibling::div//span[span[text()='Databases']]/" \ + "preceding-sibling::i[@class='directory-toggle open']" \ + % server_name + + # Database Node + @staticmethod + def database_node(database_name): + return "//div[@data-depth='4']/span/span[text()='%s']" % database_name @staticmethod - def sub_nodes_of_databases_node(server_name): - xpath = "//div[div[div[span[span[contains(text(),'%s')]]]]]/" \ - "following-sibling::ul/li[1]/div/following-sibling::ul/li/" \ - "div/div/div/div/div/span[2]/span[@class='aciTreeText']" % \ - server_name - return xpath + def database_node_exp_status(database_name): + return "//i[@class='directory-toggle open']/following-sibling::" \ + "span//span[text()='%s']" % database_name + + # Schemas Node + @staticmethod + def schemas_node(database_name): + return "//div[div[span[span[starts-with(text(),'%s')]]]]/" \ + "following-sibling::div//span[text()='Schemas']" % database_name @staticmethod - def sub_nodes_of_databases_node_exp_status(server_name): - xpath = "//div[div[div[span[span[contains(text(), '%s')]]]]]/" \ - "following-sibling::ul/li[1]/div/following-sibling::ul/li/" \ - "div" % server_name - return xpath + def schemas_node_exp_status(database_name): + return "//div[div[span[span[starts-with(text(),'%s')]]]]/" \ + "following-sibling::div//span[span[text()='Schemas']]/" \ + "preceding-sibling::i[@class='directory-toggle open']" \ + % database_name + + # Schema Node + @staticmethod + def schema_node(schema_name): + return "//div[@id='tree']//span[text()='%s']" % schema_name @staticmethod - def sub_nodes_of_database_node(database_name): - xpath = "//div[div[div[div[div[span[span[contains(text()," \ - "'%s')]]]]]]]/following-sibling::ul/li/div/div/div/div/div/" \ - "div/span[2]/span[2]" % database_name - return xpath + def schema_node_exp_status(schema_name): + return "//i[@class='directory-toggle open']/" \ + "following-sibling::span//span[text()='%s']" % schema_name + + # Tables Node + @staticmethod + def tables_node(schema_name): + return "//div[div[span[span[starts-with(text(),'%s')]]]]/" \ + "following-sibling::div//span[text()='Tables']" % schema_name @staticmethod - def sub_nodes_of_database_node_exp_status(database_name): - xpath = "//div[div[div[div[div[span[span[contains(text(), " \ - "'%s')]]]]]]]/following-sibling::ul/li/div" % database_name - return xpath + def tables_node_exp_status(schema_name): + return "//div[div[span[span[starts-with(text(),'%s')]]]]/" \ + "following-sibling::div//span[span[text()='Tables']]/" \ + "preceding-sibling::i[@class='directory-toggle open']"\ + % schema_name + + # Schema child + @staticmethod + def schema_child_node_exp_status(schema_name, child_node_name): + return "//div[div[span[span[starts-with(text(),'%s')]]]]/" \ + "following-sibling::div//span[span[text()='%s']]/" \ + "preceding-sibling::i[@class='directory-toggle open']" \ + % (schema_name, child_node_name) @staticmethod - def sub_nodes_of_schemas_node(database_name): - xpath = "//div[div[div[div[div[span[span[text()='%s']]]]]]]/" \ - "following-sibling::ul/li[" \ - "@role='presentation']/ul/li/div//div/span/span[" \ - "@class='aciTreeText']" % database_name - return xpath + def schema_child_node(schema_name, child_node_name): + return "//div[div[span[span[starts-with(text(),'%s')]]]]/" \ + "following-sibling::div//span[text()='%s']" \ + % (schema_name, child_node_name) + + # Database child + @staticmethod + def database_child_node_exp_status(database_name, child_node_name): + return "//div[div[span[span[starts-with(text(),'%s')]]]]/" \ + "following-sibling::div//span[span[text()='%s']]/" \ + "preceding-sibling::i[@class='directory-toggle open']"\ + % (database_name, child_node_name) @staticmethod - def sub_nodes_of_schemas_node_exp_status(database_name): - xpath = "//div[div[div[div[div[span[span[text()='%s']]]]]]]/" \ - "following-sibling::ul/li[@role='presentation']/ul/li/div" \ - % database_name - return xpath + def database_child_node(database_name, child_node_name): + return "//div[div[span[span[starts-with(text(),'%s')]]]]/" \ + "following-sibling::div//span[text()='%s']" \ + % (database_name, child_node_name) + + # Server child + @staticmethod + def server_child_node_exp_status(server_name, child_node_name): + return "//div[div[span[span[starts-with(text(),'%s')]]]]/" \ + "following-sibling::div//span[span[text()='%s']]/" \ + "preceding-sibling::i[@class='directory-toggle open']"\ + % (server_name, child_node_name) @staticmethod - def sub_nodes_of_schema_node(database_name): - xpath = "//div[div[div[div[div[span[span[text()='%s']]]]]]]/" \ - "following-sibling::ul/li[" \ - "@role='presentation']/ul/li/ul/li/div//div/span[2]/span[2]" \ - % database_name - return xpath + def server_child_node(server_name, child_node_name): + return "//div[div[span[span[starts-with(text(),'%s')]]]]/" \ + "following-sibling::div//span[text()='%s']" \ + % (server_name, child_node_name) + # Table Node @staticmethod - def sub_nodes_of_schema_node_exp_status(database_name): - xpath = "//div[div[div[div[div[span[span[text()='%s']]]]]]]/" \ - "following-sibling::ul/li[@role='presentation']" \ - "/ul/li/ul/li/div" % database_name - return xpath + def table_node(table_name): + return "//div[@data-depth='8']/span/span[text()='%s']" % table_name + + # Function Node + @staticmethod + def function_node(table_name): + return "//div[@data-depth='8']/span/span[text()='%s']" % table_name + + # Role Node + @staticmethod + def role_node(role_name): + return "//div[@data-depth='4']/span/span[text()='%s']" % role_name + + # Context element option + @staticmethod + def context_menu_element(schema_name): + return "//li/span[text()='%s']" % schema_name + + # Old xpaths + # server_group_sub_nodes_exp_status = \ + # "//div[div[span[span[contains(text(),'Servers')]]]]" \ + # "/following-sibling::ul/li/div" + # + # server_group_sub_nodes_connected_status = \ + # "//div[div[span[span[contains(text(), 'Servers')]]]]/" \ + # "following-sibling::ul/li/div/div/div/span[2]" + # + # specified_tree_node = \ + # "//div[@id='tree']//span[@class='aciTreeItem']/" \ + # "span[(@class='aciTreeText') and text()='{}']" + # + # specified_tree_node_exp_status = \ + # "//div[@id='tree']//span[@class='aciTreeItem']/" \ + # "span[(@class='aciTreeText') and text()='{}']" \ + # "//ancestor::*[@class='aciTreeLine']" + # + # sub_nodes_of_tables_node = \ + # "//div[div[div[div[div[div[div[div[span[span[" \ + # "contains(text(),'Tables')]]]]]]]]]]/" \ + # "following-sibling::ul/li/div//div/span[2]/span[2]" + # + # sub_nodes_of_functions_node = \ + # "//div[div[div[div[div[div[div[div[span[span[" \ + # "contains(text(),'Functions')]]]]]]]]]]/" \ + # "following-sibling::ul/li/div//div/span[2]/span[2]" + # + # sub_nodes_of_login_group_node = \ + # "//div[div[div[span[span[contains(text(),'Login/Group Roles')]]]]]" \ + # "/following::ul/li/div[@class='aciTreeLine']" + # + # @staticmethod + # def sub_nodes_of_a_server_node(server_name): + # xpath = "//div[div[div[span[span[contains(text(),'%s')]]]]]/" \ + # "following-sibling::ul/li/div[@class='aciTreeLine']" % \ + # server_name + # return xpath + # + # @staticmethod + # def sub_nodes_of_a_server_node_exp_status(server_name): + # xpath = "//div[div[div[span[span[contains(text(),'%s')]]]]]/" \ + # "following-sibling::ul/li/div" % server_name + # return xpath + # + # @staticmethod + # def databases_node_of_a_server_node(server_name): + # xpath = "//div[div[div[span[span[contains(text(),'%s')]]]]]/" \ + # "following-sibling::ul/li/div/div/div/div/span[2]/span[2 " \ + # "and text()='Databases ']" % server_name + # return xpath + # + # @staticmethod + # def sub_nodes_of_databases_node(server_name): + # xpath = "//div[div[div[span[span[contains(text(),'%s')]]]]]/" \ + # "following-sibling::ul/li[1]/div/following-sibling::ul/li/" \ + # "div/div/div/div/div/span[2]/span[@class='aciTreeText']" % \ + # server_name + # return xpath + # + # @staticmethod + # def sub_nodes_of_databases_node_exp_status(server_name): + # xpath = "//div[div[div[span[span[contains(text(), '%s')]]]]]/" \ + # "following-sibling::ul/li[1]/div/following-sibling::ul/li/" \ + # "div" % server_name + # return xpath + # + # @staticmethod + # def sub_nodes_of_database_node(database_name): + # xpath = "//div[div[div[div[div[span[span[contains(text()," \ + # "'%s')]]]]]]]/following-sibling::" \ + # "ul/li/div/div/div/div/div/div/span[2]/span[2]"\ + # % database_name + # return xpath + # + # @staticmethod + # def sub_nodes_of_database_node_exp_status(database_name): + # xpath = "//div[div[div[div[div[span[span[contains(text(), " \ + # "'%s')]]]]]]]/following-sibling::ul/li/div" % database_name + # return xpath + # + # @staticmethod + # def sub_nodes_of_schemas_node(database_name): + # xpath = "//div[div[div[div[div[span[span[text()='%s']]]]]]]/" \ + # "following-sibling::ul/li[" \ + # "@role='presentation']/ul/li/div//div/span/span[" \ + # "@class='aciTreeText']" % database_name + # return xpath + # + # @staticmethod + # def sub_nodes_of_schemas_node_exp_status(database_name): + # xpath = "//div[div[div[div[div[span[span[text()='%s']]]]]]]/" \ + # "following-sibling::ul/li[@role='presentation']/ul/li/div" \ + # % database_name + # return xpath + # + # @staticmethod + # def sub_nodes_of_schema_node(database_name): + # xpath = "//div[div[div[div[div[span[span[text()='%s']]]]]]]/" \ + # "following-sibling::ul/li[@role='presentation']" \ + # "/ul/li/ul/li/div//div/span[2]/span[2]" % database_name + # return xpath + # + # @staticmethod + # def sub_nodes_of_schema_node_exp_status(database_name): + # xpath = "//div[div[div[div[div[span[span[text()='%s']]]]]]]/" \ + # "following-sibling::ul/li[@role='presentation']" \ + # "/ul/li/ul/li/div" % database_name + # return xpath diff --git a/web/regression/python_test_utils/test_utils.py b/web/regression/python_test_utils/test_utils.py index 85963296f..10397e122 100644 --- a/web/regression/python_test_utils/test_utils.py +++ b/web/regression/python_test_utils/test_utils.py @@ -422,6 +422,32 @@ def does_function_exist(server, db_name, fun_name): return str(result[0][0]) +def grant_role(server, db_name, role_name="test_role", + grant_role="

test

"): + try: + connection = get_db_connection( + db_name, + server['username'], + server['db_password'], + server['host'], + server['port'], + server['sslmode'] + ) + old_isolation_level = connection.isolation_level + connection.set_isolation_level(0) + pg_cursor = connection.cursor() + sql_query = '''GRANT "%s" TO %s;''' % (grant_role, role_name) + + pg_cursor.execute( + sql_query + ) + connection.set_isolation_level(old_isolation_level) + connection.commit() + + except Exception: + traceback.print_exc(file=sys.stderr) + + def create_role(server, db_name, role_name="test_role"): try: connection = get_db_connection( diff --git a/web/regression/requirements.txt b/web/regression/requirements.txt index 4a14802c1..0a5ba0f36 100644 --- a/web/regression/requirements.txt +++ b/web/regression/requirements.txt @@ -25,5 +25,5 @@ python-mimeparse==1.6.0 testscenarios==0.5.0 testtools==2.3.0 traceback2==1.4.0 -selenium==3.14.0 +selenium==4.0.0 coverage==5.0.1 diff --git a/web/regression/runtests.py b/web/regression/runtests.py index 7503f7c63..7bc2ca4d5 100644 --- a/web/regression/runtests.py +++ b/web/regression/runtests.py @@ -295,9 +295,9 @@ def setup_webdriver_specification(arguments): 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("--window-size=1790,1080") options.add_argument("--disable-infobars") - options.add_experimental_option('w3c', False) + # options.add_experimental_option('w3c', False) driver_local = webdriver.Chrome(chrome_options=options) # maximize browser window