From ebeb768a53680093cbed5157f7367cdb2a362dc3 Mon Sep 17 00:00:00 2001 From: Yogesh Mahajan Date: Thu, 30 Jan 2025 10:26:11 +0530 Subject: [PATCH] Ensure the double-click event is listened to even if the user clicks after the label. --- .../components/PgTree/FileTreeItem/index.tsx | 46 +++--- .../feature_tests/browser_tool_bar_test.py | 19 ++- .../feature_utils/tree_area_locators.py | 139 ++---------------- 3 files changed, 55 insertions(+), 149 deletions(-) diff --git a/web/pgadmin/static/js/components/PgTree/FileTreeItem/index.tsx b/web/pgadmin/static/js/components/PgTree/FileTreeItem/index.tsx index 268785156..547415046 100644 --- a/web/pgadmin/static/js/components/PgTree/FileTreeItem/index.tsx +++ b/web/pgadmin/static/js/components/PgTree/FileTreeItem/index.tsx @@ -83,29 +83,28 @@ export class FileTreeItem extends React.Component{/* taken care by parent */}} - // required for rendering context menus when opened through context menu button on keyboard - ref={this.handleDivRef} - draggable={true}> + +
{/* taken care by parent */}} + // required for rendering context menus when opened through context menu button on keyboard + ref={this.handleDivRef} + draggable={true}> - {!isNewPrompt && fileOrDir === 'directory' ? - - : null - } + {!isNewPrompt && fileOrDir === 'directory' ? + + : null + } - { item._metadata?.data?.icon ? : null @@ -120,8 +119,9 @@ export class FileTreeItem extends React.Component ))} - -
); + +
+ ); } public componentDidMount() { diff --git a/web/regression/feature_tests/browser_tool_bar_test.py b/web/regression/feature_tests/browser_tool_bar_test.py index 0397bd5d4..7ba9d6abb 100644 --- a/web/regression/feature_tests/browser_tool_bar_test.py +++ b/web/regression/feature_tests/browser_tool_bar_test.py @@ -11,11 +11,14 @@ import sys import secrets import time +from selenium.webdriver.support.wait import WebDriverWait + from regression.python_test_utils import test_utils from regression.feature_utils.locators import BrowserToolBarLocators from regression.feature_utils.base_feature_test import BaseFeatureTest from regression.feature_utils.tree_area_locators import TreeAreaLocators from selenium.webdriver.common.by import By +from selenium.webdriver.support import expected_conditions as EC class BrowserToolBarFeatureTest(BaseFeatureTest): @@ -68,6 +71,14 @@ class BrowserToolBarFeatureTest(BaseFeatureTest): 'db_password'], self.test_db), 'Tree is not expanded to database node') + + WebDriverWait(self.driver, 3).until( + EC.visibility_of_element_located( + (By.CSS_SELECTOR, + BrowserToolBarLocators.open_query_tool_button_css) + ), "Timed out waiting for execute query button to appear" + ) + self.assertTrue(self.page.retry_click( (By.CSS_SELECTOR, BrowserToolBarLocators.open_query_tool_button_css), @@ -87,7 +98,13 @@ class BrowserToolBarFeatureTest(BaseFeatureTest): table_node = self.page.check_if_element_exists_with_scroll( TreeAreaLocators.table_node(self.test_table_name)) table_node.click() - time.sleep(2) + + WebDriverWait(self.driver, 3).until( + EC.visibility_of_element_located( + (By.CSS_SELECTOR, + BrowserToolBarLocators.view_table_data_button_css) + ), "Timed out waiting for execute query button to appear" + ) self.assertTrue(self.page.retry_click( (By.CSS_SELECTOR, diff --git a/web/regression/feature_utils/tree_area_locators.py b/web/regression/feature_utils/tree_area_locators.py index d79194df9..30fb494b0 100644 --- a/web/regression/feature_utils/tree_area_locators.py +++ b/web/regression/feature_utils/tree_area_locators.py @@ -19,7 +19,7 @@ class TreeAreaLocators: @staticmethod def server_group_node_exp_status(server_group_name): return "//i[@class='directory-toggle open']/following-sibling::" \ - "div//span[starts-with(text(),'%s')]" % server_group_name + "span//span[starts-with(text(),'%s')]" % server_group_name # Server Node @staticmethod @@ -31,7 +31,7 @@ class TreeAreaLocators: @staticmethod def server_node_exp_status(server_name): return "//i[@class='directory-toggle open']/following-sibling::" \ - "div//span[starts-with(text(),'%s')]" % server_name + "span//span[starts-with(text(),'%s')]" % server_name # Server Connection @staticmethod @@ -49,20 +49,19 @@ class TreeAreaLocators: @staticmethod def databases_node_exp_status(server_name): return "//div[div[div[span[span[starts-with(text(),'%s')]]]]]/" \ - "following-sibling::div//div[span[span[text()='Databases']]]/" \ + "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']/div/span/span[text()='%s']" \ - % database_name + return "//div[@data-depth='4']/span/span[text()='%s']" % database_name @staticmethod def database_node_exp_status(database_name): return "//i[@class='directory-toggle open']/following-sibling::" \ - "div//span[text()='%s']" % database_name + "span//span[text()='%s']" % database_name # Schemas Node @staticmethod @@ -73,7 +72,7 @@ class TreeAreaLocators: @staticmethod def schemas_node_exp_status(database_name): return "//div[div[div[span[span[starts-with(text(),'%s')]]]]]/" \ - "following-sibling::div//div[span[span[text()='Schemas']]]/" \ + "following-sibling::span//div[span[span[text()='Schemas']]]/" \ "preceding-sibling::i[@class='directory-toggle open']" \ % database_name @@ -86,25 +85,25 @@ class TreeAreaLocators: @staticmethod def schema_node_exp_status(schema_name): return "//i[@class='directory-toggle open']/" \ - "following-sibling::div//span[text()='%s']" % schema_name + "following-sibling::span//span[text()='%s']" % schema_name # Tables Node @staticmethod def tables_node(schema_name): - return "//div[divdiv[[span[span[starts-with(text(),'%s')]]]]]/" \ - "following-sibling::div//span[text()='Tables']" % schema_name + return ("//div[div[div[span/span[text()='%s']]]]/" + "following-sibling::div//span[text()='Tables']" % schema_name) @staticmethod def tables_node_exp_status(schema_name): return "//div[div[span[span[starts-with(text(),'%s')]]]]/" \ - "following-sibling::div//div[span[span[text()='Tables']]]/" \ + "following-sibling::span//div[span[span[text()='Tables']]]/" \ "preceding-sibling::i[@class='directory-toggle open']"\ % schema_name # Schema child child_node_exp_status = \ "//div[div[div[span[span[starts-with(text(),'%s')]]]]]/" \ - "following-sibling::div//div[span[span[text()='%s']]]/" \ + "following-sibling::div//span[span[text()='%s']]/" \ "preceding-sibling::i[@class='directory-toggle open']" child_node = "//div[div[div[span[span[starts-with(text(),'%s')]]]]]/" \ @@ -148,129 +147,19 @@ class TreeAreaLocators: # Table Node @staticmethod def table_node(table_name): - return "//div[@data-depth='8']/div/span/span[text()='%s']" % 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']/div/span/span[text()='%s']" % 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']/div/span/span[text()='%s']" % role_name + return "//div[@data-depth='4']/span/span[text()='%s']" % role_name # Context element option @staticmethod def context_menu_element(schema_name): return "[role='menuitem'][data-label='%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='id-object-explorer']//span[@class='aciTreeItem']/" \ - # "span[(@class='aciTreeText') and text()='{}']" - # - # specified_tree_node_exp_status = \ - # "//div[@id='id-object-explorer']//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