Skip to content

Commit 896abc7

Browse files
Esnure double click events are listened if user clicks after label.
1 parent 707d037 commit 896abc7

File tree

3 files changed

+57
-151
lines changed

3 files changed

+57
-151
lines changed

web/pgadmin/static/js/components/PgTree/FileTreeItem/index.tsx

Lines changed: 25 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -83,29 +83,28 @@ export class FileTreeItem extends React.Component<IItemRendererXProps & IItemRen
8383
const tags = item._metadata.data?.tags ?? [];
8484

8585
return (
86-
<div
87-
className={cn('file-entry', {
88-
renaming: isRenamePrompt,
89-
prompt: isRenamePrompt || isNewPrompt,
90-
new: isNewPrompt,
91-
}, fileOrDir, decorations ? decorations.classlist : null, `depth-${item.depth}`, extraClasses)}
92-
data-depth={item.depth}
93-
onContextMenu={this.handleContextMenu}
94-
onClick={this.handleClick}
95-
onDragStart={this.handleDragStartItem}
96-
onMouseEnter={this.handleMouseEnter}
97-
onMouseLeave={this.handleMouseLeave}
98-
onKeyDown={()=>{/* taken care by parent */}}
99-
// required for rendering context menus when opened through context menu button on keyboard
100-
ref={this.handleDivRef}
101-
draggable={true}>
102-
103-
{!isNewPrompt && fileOrDir === 'directory' ?
104-
<i className={cn('directory-toggle', isDirExpanded ? 'open' : '')} />
105-
: null
106-
}
107-
108-
<DoubleClickHandler onDoubleClick={this.handleDoubleClick} onSingleClick={this.handleClick} >
86+
<DoubleClickHandler onDoubleClick={this.handleDoubleClick} onSingleClick={this.handleClick}>
87+
<div
88+
className={cn('file-entry', {
89+
renaming: isRenamePrompt,
90+
prompt: isRenamePrompt || isNewPrompt,
91+
new: isNewPrompt,
92+
}, fileOrDir, decorations ? decorations.classlist : null, `depth-${item.depth}`, extraClasses)}
93+
data-depth={item.depth}
94+
onContextMenu={this.handleContextMenu}
95+
onDragStart={this.handleDragStartItem}
96+
onMouseEnter={this.handleMouseEnter}
97+
onMouseLeave={this.handleMouseLeave}
98+
onKeyDown={()=>{/* taken care by parent */}}
99+
// required for rendering context menus when opened through context menu button on keyboard
100+
ref={this.handleDivRef}
101+
draggable={true}>
102+
103+
{!isNewPrompt && fileOrDir === 'directory' ?
104+
<i className={cn('directory-toggle', isDirExpanded ? 'open' : '')} />
105+
: null
106+
}
107+
109108
<span className='file-label'>{
110109
item._metadata?.data?.icon ?
111110
<i className={cn('file-icon', item._metadata?.data?.icon ? item._metadata.data.icon : fileOrDir)} /> : null
@@ -120,8 +119,9 @@ export class FileTreeItem extends React.Component<IItemRendererXProps & IItemRen
120119
</div>
121120
))}
122121
</span>
123-
</DoubleClickHandler>
124-
</div>);
122+
</div>
123+
</DoubleClickHandler>
124+
);
125125
}
126126

127127
public componentDidMount() {

web/regression/feature_tests/browser_tool_bar_test.py

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,14 @@
1111
import secrets
1212
import time
1313

14+
from selenium.webdriver.support.wait import WebDriverWait
15+
1416
from regression.python_test_utils import test_utils
1517
from regression.feature_utils.locators import BrowserToolBarLocators
1618
from regression.feature_utils.base_feature_test import BaseFeatureTest
1719
from regression.feature_utils.tree_area_locators import TreeAreaLocators
1820
from selenium.webdriver.common.by import By
21+
from selenium.webdriver.support import expected_conditions as EC
1922

2023

2124
class BrowserToolBarFeatureTest(BaseFeatureTest):
@@ -68,6 +71,14 @@ def test_query_tool_button(self):
6871
'db_password'],
6972
self.test_db),
7073
'Tree is not expanded to database node')
74+
75+
WebDriverWait(self.driver, 3).until(
76+
EC.visibility_of_element_located(
77+
(By.CSS_SELECTOR,
78+
BrowserToolBarLocators.open_query_tool_button_css)
79+
), "Timed out waiting for execute query button to appear"
80+
)
81+
7182
self.assertTrue(self.page.retry_click(
7283
(By.CSS_SELECTOR,
7384
BrowserToolBarLocators.open_query_tool_button_css),
@@ -87,7 +98,13 @@ def test_view_data_tool_button(self):
8798
table_node = self.page.check_if_element_exists_with_scroll(
8899
TreeAreaLocators.table_node(self.test_table_name))
89100
table_node.click()
90-
time.sleep(2)
101+
102+
WebDriverWait(self.driver, 3).until(
103+
EC.visibility_of_element_located(
104+
(By.CSS_SELECTOR,
105+
BrowserToolBarLocators.view_table_data_button_css)
106+
), "Timed out waiting for execute query button to appear"
107+
)
91108

92109
self.assertTrue(self.page.retry_click(
93110
(By.CSS_SELECTOR,

web/regression/feature_utils/tree_area_locators.py

Lines changed: 14 additions & 125 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ def server_group_node(server_group_name):
1919
@staticmethod
2020
def server_group_node_exp_status(server_group_name):
2121
return "//i[@class='directory-toggle open']/following-sibling::" \
22-
"div//span[starts-with(text(),'%s')]" % server_group_name
22+
"span//span[starts-with(text(),'%s')]" % server_group_name
2323

2424
# Server Node
2525
@staticmethod
@@ -31,7 +31,7 @@ def server_node(server_name):
3131
@staticmethod
3232
def server_node_exp_status(server_name):
3333
return "//i[@class='directory-toggle open']/following-sibling::" \
34-
"div//span[starts-with(text(),'%s')]" % server_name
34+
"span//span[starts-with(text(),'%s')]" % server_name
3535

3636
# Server Connection
3737
@staticmethod
@@ -49,20 +49,19 @@ def databases_node(server_name):
4949
@staticmethod
5050
def databases_node_exp_status(server_name):
5151
return "//div[div[div[span[span[starts-with(text(),'%s')]]]]]/" \
52-
"following-sibling::div//div[span[span[text()='Databases']]]/" \
52+
"following-sibling::div//span[span[text()='Databases']]/" \
5353
"preceding-sibling::i[@class='directory-toggle open']" \
5454
% server_name
5555

5656
# Database Node
5757
@staticmethod
5858
def database_node(database_name):
59-
return "//div[@data-depth='4']/div/span/span[text()='%s']" \
60-
% database_name
59+
return "//div[@data-depth='4']/span/span[text()='%s']" % database_name
6160

6261
@staticmethod
6362
def database_node_exp_status(database_name):
6463
return "//i[@class='directory-toggle open']/following-sibling::" \
65-
"div//span[text()='%s']" % database_name
64+
"span//span[text()='%s']" % database_name
6665

6766
# Schemas Node
6867
@staticmethod
@@ -73,7 +72,7 @@ def schemas_node(database_name):
7372
@staticmethod
7473
def schemas_node_exp_status(database_name):
7574
return "//div[div[div[span[span[starts-with(text(),'%s')]]]]]/" \
76-
"following-sibling::div//div[span[span[text()='Schemas']]]/" \
75+
"following-sibling::span//div[span[span[text()='Schemas']]]/" \
7776
"preceding-sibling::i[@class='directory-toggle open']" \
7877
% database_name
7978

@@ -86,25 +85,25 @@ def schema_node(schema_name):
8685
@staticmethod
8786
def schema_node_exp_status(schema_name):
8887
return "//i[@class='directory-toggle open']/" \
89-
"following-sibling::div//span[text()='%s']" % schema_name
88+
"following-sibling::span//span[text()='%s']" % schema_name
9089

9190
# Tables Node
9291
@staticmethod
9392
def tables_node(schema_name):
94-
return "//div[divdiv[[span[span[starts-with(text(),'%s')]]]]]/" \
95-
"following-sibling::div//span[text()='Tables']" % schema_name
93+
return ("//div[div[div[span/span[text()='%s']]]]/"
94+
"following-sibling::div//span[text()='Tables']" % schema_name)
9695

9796
@staticmethod
9897
def tables_node_exp_status(schema_name):
9998
return "//div[div[span[span[starts-with(text(),'%s')]]]]/" \
100-
"following-sibling::div//div[span[span[text()='Tables']]]/" \
99+
"following-sibling::span//div[span[span[text()='Tables']]]/" \
101100
"preceding-sibling::i[@class='directory-toggle open']"\
102101
% schema_name
103102

104103
# Schema child
105104
child_node_exp_status = \
106105
"//div[div[div[span[span[starts-with(text(),'%s')]]]]]/" \
107-
"following-sibling::div//div[span[span[text()='%s']]]/" \
106+
"following-sibling::div//span[span[text()='%s']]/" \
108107
"preceding-sibling::i[@class='directory-toggle open']"
109108

110109
child_node = "//div[div[div[span[span[starts-with(text(),'%s')]]]]]/" \
@@ -148,129 +147,19 @@ def server_child_node(server_name, child_node_name):
148147
# Table Node
149148
@staticmethod
150149
def table_node(table_name):
151-
return "//div[@data-depth='8']/div/span/span[text()='%s']" % table_name
150+
return "//div[@data-depth='8']/span/span[text()='%s']" % table_name
152151

153152
# Function Node
154153
@staticmethod
155154
def function_node(table_name):
156-
return "//div[@data-depth='8']/div/span/span[text()='%s']" % table_name
155+
return "//div[@data-depth='8']/span/span[text()='%s']" % table_name
157156

158157
# Role Node
159158
@staticmethod
160159
def role_node(role_name):
161-
return "//div[@data-depth='4']/div/span/span[text()='%s']" % role_name
160+
return "//div[@data-depth='4']/span/span[text()='%s']" % role_name
162161

163162
# Context element option
164163
@staticmethod
165164
def context_menu_element(schema_name):
166165
return "[role='menuitem'][data-label='%s']" % schema_name
167-
168-
# Old xpaths
169-
# server_group_sub_nodes_exp_status = \
170-
# "//div[div[span[span[contains(text(),'Servers')]]]]" \
171-
# "/following-sibling::ul/li/div"
172-
#
173-
# server_group_sub_nodes_connected_status = \
174-
# "//div[div[span[span[contains(text(), 'Servers')]]]]/" \
175-
# "following-sibling::ul/li/div/div/div/span[2]"
176-
#
177-
# specified_tree_node = \
178-
# "//div[@id='id-object-explorer']//span[@class='aciTreeItem']/" \
179-
# "span[(@class='aciTreeText') and text()='{}']"
180-
#
181-
# specified_tree_node_exp_status = \
182-
# "//div[@id='id-object-explorer']//span[@class='aciTreeItem']/" \
183-
# "span[(@class='aciTreeText') and text()='{}']" \
184-
# "//ancestor::*[@class='aciTreeLine']"
185-
#
186-
# sub_nodes_of_tables_node = \
187-
# "//div[div[div[div[div[div[div[div[span[span[" \
188-
# "contains(text(),'Tables')]]]]]]]]]]/" \
189-
# "following-sibling::ul/li/div//div/span[2]/span[2]"
190-
#
191-
# sub_nodes_of_functions_node = \
192-
# "//div[div[div[div[div[div[div[div[span[span[" \
193-
# "contains(text(),'Functions')]]]]]]]]]]/" \
194-
# "following-sibling::ul/li/div//div/span[2]/span[2]"
195-
#
196-
# sub_nodes_of_login_group_node = \
197-
# "//div[div[div[span[span[contains(text(),'Login/Group Roles')]]]]]" \
198-
# "/following::ul/li/div[@class='aciTreeLine']"
199-
#
200-
# @staticmethod
201-
# def sub_nodes_of_a_server_node(server_name):
202-
# xpath = "//div[div[div[span[span[contains(text(),'%s')]]]]]/" \
203-
# "following-sibling::ul/li/div[@class='aciTreeLine']" % \
204-
# server_name
205-
# return xpath
206-
#
207-
# @staticmethod
208-
# def sub_nodes_of_a_server_node_exp_status(server_name):
209-
# xpath = "//div[div[div[span[span[contains(text(),'%s')]]]]]/" \
210-
# "following-sibling::ul/li/div" % server_name
211-
# return xpath
212-
#
213-
# @staticmethod
214-
# def databases_node_of_a_server_node(server_name):
215-
# xpath = "//div[div[div[span[span[contains(text(),'%s')]]]]]/" \
216-
# "following-sibling::ul/li/div/div/div/div/span[2]/span[2 " \
217-
# "and text()='Databases ']" % server_name
218-
# return xpath
219-
#
220-
# @staticmethod
221-
# def sub_nodes_of_databases_node(server_name):
222-
# xpath = "//div[div[div[span[span[contains(text(),'%s')]]]]]/" \
223-
# "following-sibling::ul/li[1]/div/following-sibling::ul/li/" \
224-
# "div/div/div/div/div/span[2]/span[@class='aciTreeText']" % \
225-
# server_name
226-
# return xpath
227-
#
228-
# @staticmethod
229-
# def sub_nodes_of_databases_node_exp_status(server_name):
230-
# xpath = "//div[div[div[span[span[contains(text(), '%s')]]]]]/" \
231-
# "following-sibling::ul/li[1]/div/following-sibling::ul/li/" \
232-
# "div" % server_name
233-
# return xpath
234-
#
235-
# @staticmethod
236-
# def sub_nodes_of_database_node(database_name):
237-
# xpath = "//div[div[div[div[div[span[span[contains(text()," \
238-
# "'%s')]]]]]]]/following-sibling::" \
239-
# "ul/li/div/div/div/div/div/div/span[2]/span[2]"\
240-
# % database_name
241-
# return xpath
242-
#
243-
# @staticmethod
244-
# def sub_nodes_of_database_node_exp_status(database_name):
245-
# xpath = "//div[div[div[div[div[span[span[contains(text(), " \
246-
# "'%s')]]]]]]]/following-sibling::ul/li/div" % database_name
247-
# return xpath
248-
#
249-
# @staticmethod
250-
# def sub_nodes_of_schemas_node(database_name):
251-
# xpath = "//div[div[div[div[div[span[span[text()='%s']]]]]]]/" \
252-
# "following-sibling::ul/li[" \
253-
# "@role='presentation']/ul/li/div//div/span/span[" \
254-
# "@class='aciTreeText']" % database_name
255-
# return xpath
256-
#
257-
# @staticmethod
258-
# def sub_nodes_of_schemas_node_exp_status(database_name):
259-
# xpath = "//div[div[div[div[div[span[span[text()='%s']]]]]]]/" \
260-
# "following-sibling::ul/li[@role='presentation']/ul/li/div" \
261-
# % database_name
262-
# return xpath
263-
#
264-
# @staticmethod
265-
# def sub_nodes_of_schema_node(database_name):
266-
# xpath = "//div[div[div[div[div[span[span[text()='%s']]]]]]]/" \
267-
# "following-sibling::ul/li[@role='presentation']" \
268-
# "/ul/li/ul/li/div//div/span[2]/span[2]" % database_name
269-
# return xpath
270-
#
271-
# @staticmethod
272-
# def sub_nodes_of_schema_node_exp_status(database_name):
273-
# xpath = "//div[div[div[div[div[span[span[text()='%s']]]]]]]/" \
274-
# "following-sibling::ul/li[@role='presentation']" \
275-
# "/ul/li/ul/li/div" % database_name
276-
# return xpath

0 commit comments

Comments
 (0)