');
myPanel.layout().addItem($frameArea);
that.panel = myPanel;
var frame = new wcIFrame($frameArea, myPanel);
diff --git a/web/pgadmin/feature_tests/browser_tool_bar_test.py b/web/pgadmin/feature_tests/browser_tool_bar_test.py
index 944363dc..82486059 100644
--- a/web/pgadmin/feature_tests/browser_tool_bar_test.py
+++ b/web/pgadmin/feature_tests/browser_tool_bar_test.py
@@ -82,7 +82,7 @@ class BrowserToolBarFeatureTest(BaseFeatureTest):
self.page.select_tree_item(self.test_db)
self.page.toggle_open_tree_item('Schemas')
self.page.toggle_open_tree_item('public')
- self.page.toggle_open_tree_item('Tables')
+ self.page.toggle_open_tables_node()
self.page.select_tree_item(self.test_table_name)
retry_count = 0
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 382020f6..0837b84a 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
@@ -43,9 +43,6 @@ class CopySelectedQueryResultsFeatureTest(BaseFeatureTest):
self.page.toggle_open_tree_item(self.test_db)
self.page.open_query_tool()
- self.page.driver.switch_to_frame(
- self.page.driver.find_element_by_tag_name("iframe"))
-
self.page.fill_codemirror_area_with(
"SELECT * FROM %s ORDER BY some_column" % self.test_table_name)
diff --git a/web/pgadmin/feature_tests/file_manager_test.py b/web/pgadmin/feature_tests/file_manager_test.py
index 90548079..288dc983 100644
--- a/web/pgadmin/feature_tests/file_manager_test.py
+++ b/web/pgadmin/feature_tests/file_manager_test.py
@@ -17,6 +17,7 @@ from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
from regression.feature_utils.base_feature_test import BaseFeatureTest
+from .locators import QueryToolLocatorsCss
class CheckFileManagerFeatureTest(BaseFeatureTest):
@@ -41,7 +42,7 @@ class CheckFileManagerFeatureTest(BaseFeatureTest):
os.remove(self.XSS_FILE)
def after(self):
- self.page.close_query_tool('.sql', False)
+ self.page.close_query_tool(False)
self.page.remove_server(self.server)
def runTest(self):
@@ -64,14 +65,11 @@ class CheckFileManagerFeatureTest(BaseFeatureTest):
self.page.open_query_tool()
def _create_new_file(self):
- self.page.find_by_id("btn-save").click()
- self.page.wait_for_query_tool_loading_indicator_to_disappear()
- self.page.find_by_css_selector('.change_file_types')
+ self.page.find_by_css_selector(QueryToolLocatorsCss.btn_save).click()
# Set the XSS value in input
- self.page.find_by_id("file-input-path").clear()
- self.page.find_by_id("file-input-path").send_keys(
- self.XSS_FILE
- )
+ print('Create file')
+ self.page.find_by_css_selector('.change_file_types')
+ self.page.fill_input_by_css_selector("#file-input-path", self.XSS_FILE)
# Save the file
self.page.click_modal('Create')
self.page.wait_for_query_tool_loading_indicator_to_disappear()
@@ -79,13 +77,8 @@ class CheckFileManagerFeatureTest(BaseFeatureTest):
def _open_file_manager_and_check_xss_file(self):
self.page.find_by_id("btn-load-file").click()
self.page.find_by_css_selector('.change_file_types')
- self.page.find_by_id("file-input-path").clear()
- self.page.find_by_id("file-input-path").send_keys(
- '/tmp/'
- )
- self.page.find_by_id("file-input-path").send_keys(
- Keys.RETURN
- )
+ self.page.fill_input_by_css_selector("#file-input-path", "/tmp/",
+ key_after_input=Keys.RETURN)
if self.page.driver.capabilities['browserName'] == 'firefox':
table = self.page.wait_for_element_to_reload(
diff --git a/web/pgadmin/feature_tests/locators.py b/web/pgadmin/feature_tests/locators.py
new file mode 100644
index 00000000..46673f10
--- /dev/null
+++ b/web/pgadmin/feature_tests/locators.py
@@ -0,0 +1,22 @@
+class QueryToolLocatorsCss:
+ btn_save = "#btn-save"
+ btn_execute_query = "#btn-flash"
+ btn_query_dropdown = "#btn-query-dropdown"
+ btn_auto_rollback = "#btn-auto-rollback"
+ btn_auto_rollback_check_status = "#btn-auto-rollback > i"
+ btn_auto_commit = "#btn-auto-commit"
+ btn_auto_commit_check_status = "#btn-auto-commit > i"
+ btn_cancel_query = "#btn-cancel-query"
+ btn_explain = "#btn-explain"
+ btn_explain_analyze = "#btn-explain-analyze"
+ btn_explain_options_dropdown = "#btn-explain-options-dropdown"
+ btn_explain_verbose = "#btn-explain-verbose"
+ btn_explain_costs = "#btn-explain-costs"
+ btn_explain_buffers = "#btn-explain-buffers"
+ btn_explain_timing = "#btn-explain-timing"
+ btn_clear_dropdown = "#btn-clear-dropdown"
+ btn_clear = "#btn-clear"
+ query_editor_panel = "#output-panel"
+ query_history_selected = "#query_list .selected"
+ query_history_detail = "#query_detail"
+ editor_panel = "#output-panel"
diff --git a/web/pgadmin/feature_tests/pg_datatype_validation_test.py b/web/pgadmin/feature_tests/pg_datatype_validation_test.py
index 7d1ed698..8a5b293b 100644
--- a/web/pgadmin/feature_tests/pg_datatype_validation_test.py
+++ b/web/pgadmin/feature_tests/pg_datatype_validation_test.py
@@ -153,7 +153,14 @@ class PGDataypeFeatureTest(BaseFeatureTest):
self.page.find_by_id("btn-flash").click()
wait = WebDriverWait(self.page.driver, 5)
- wait.until(EC.presence_of_element_located(
+
+ # wait for the visibility of the grid to appear
+ wait.until(EC.visibility_of_element_located(
+ (By.XPATH,
+ "//*[contains(@class,'column-type')]"
+ )
+ ))
+ wait.until(EC.visibility_of_element_located(
(By.XPATH,
"//*[contains(@class,'column-type') and "
"contains(.,'{}')]".format(batch['datatype'][0])
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 1c89393d..ffdda7bf 100644
--- a/web/pgadmin/feature_tests/pg_utilities_backup_restore_test.py
+++ b/web/pgadmin/feature_tests/pg_utilities_backup_restore_test.py
@@ -68,21 +68,30 @@ class PGUtilitiesBackupFeatureTest(BaseFeatureTest):
self.wait.until(EC.element_to_be_clickable(
(By.CSS_SELECTOR, ".file [name='file']"))).click()
-
- self.page.fill_input_by_field_name("file", "test_backup")
+ # .input-group-append >button
+ self.page.fill_input_by_field_name(
+ "file", "test_backup", loose_focus=True)
self.page.find_by_xpath("//button[contains(@class,'fa-save') "
"and contains(.,'Backup')]").click()
self.page.find_by_css_selector('.ajs-bg-bgprocess')
+ # status = self.page.find_by_css_selector(
+ # ".pg-bg-status .bg-success-light .pg-bg-status-text").text
+
status = self.page.find_by_css_selector(
- ".pg-bg-status .bg-success-light .pg-bg-status-text").text
+ ".pg-bg-status-text").text
+
+ print("Debug: .pg-bg-status-text %s"%status)
+
+ #.pg-bg-status-text
self.assertEquals(status, "Successfully completed.")
self.page.find_by_css_selector(
".pg-bg-more-details").click()
+ backup_file = None
# Check for XSS in Backup details
if self.is_xss_check:
self._check_detailed_window_for_xss('Backup')
@@ -99,7 +108,6 @@ class PGUtilitiesBackupFeatureTest(BaseFeatureTest):
self.assertIn("pg_dump", str(command))
- backup_file = None
if command:
backup_file = command[int(command.find('--file')) +
8:int(command.find('--host')) - 2]
@@ -117,7 +125,8 @@ class PGUtilitiesBackupFeatureTest(BaseFeatureTest):
self.wait.until(EC.element_to_be_clickable(
(By.CSS_SELECTOR, ".file [name='file']"))).click()
- self.page.fill_input_by_field_name("file", "test_backup")
+ self.page.fill_input_by_field_name(
+ "file", "test_backup", loose_focus=True)
self.page.find_by_xpath("//button[contains(@class,'fa-upload')"
" and contains(.,'Restore')]").click()
@@ -125,7 +134,7 @@ class PGUtilitiesBackupFeatureTest(BaseFeatureTest):
self.page.find_by_css_selector('.ajs-bg-bgprocess')
status = self.page.find_by_css_selector(
- ".pg-bg-status .bg-success-light .pg-bg-status-text").text
+ ".pg-bg-status-text").text
self.assertEquals(status, "Successfully completed.")
self.page.find_by_css_selector(
diff --git a/web/pgadmin/feature_tests/pg_utilities_maintenance_test.py b/web/pgadmin/feature_tests/pg_utilities_maintenance_test.py
index a03000b1..09589dd3 100644
--- a/web/pgadmin/feature_tests/pg_utilities_maintenance_test.py
+++ b/web/pgadmin/feature_tests/pg_utilities_maintenance_test.py
@@ -84,7 +84,7 @@ class PGUtilitiesMaintenanceFeatureTest(BaseFeatureTest):
def _verify_command(self):
status = self.page.find_by_css_selector(
- ".pg-bg-status .bg-success-light .pg-bg-status-text").text
+ ".pg-bg-status-text").text
self.assertEquals(status, "Successfully completed.")
self.page.find_by_css_selector(".pg-bg-more-details").click()
command = self.page.find_by_css_selector(
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 f008ca8f..4f6caf6c 100644
--- a/web/pgadmin/feature_tests/query_tool_auto_complete_tests.py
+++ b/web/pgadmin/feature_tests/query_tool_auto_complete_tests.py
@@ -21,7 +21,6 @@ class QueryToolAutoCompleteFeatureTest(BaseFeatureTest):
"""
This feature test will test the query tool auto complete feature.
"""
-
first_schema_name = ""
second_schema_name = ""
first_table_name = ""
@@ -175,6 +174,20 @@ class QueryToolAutoCompleteFeatureTest(BaseFeatureTest):
self.page.fill_codemirror_area_with(word)
ActionChains(self.page.driver).key_down(
Keys.CONTROL).send_keys(Keys.SPACE).key_up(Keys.CONTROL).perform()
- self.page.find_by_xpath(
+
+ # if IntelliSense is present then verify this
+ if self.page.check_if_element_exist_by_xpath\
+ ("//ul[@class='CodeMirror-hints default']", 2):
+ self.page.find_by_xpath(
"//ul[contains(@class, 'CodeMirror-hints') and "
"contains(., '" + expected_string + "')]")
+ 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.page.find_by_xpath(
+ "//pre[@class=' CodeMirror-line ']/span")
+ code_mirror_text = code_mirror.text
+
+ if not expected_string in code_mirror_text:
+ raise Exception("Required String %s is not "
+ "present"%expected_string)
diff --git a/web/pgadmin/feature_tests/query_tool_journey_test.py b/web/pgadmin/feature_tests/query_tool_journey_test.py
index d863f8e8..f13e6fad 100644
--- a/web/pgadmin/feature_tests/query_tool_journey_test.py
+++ b/web/pgadmin/feature_tests/query_tool_journey_test.py
@@ -15,6 +15,7 @@ from selenium.webdriver.common.keys import Keys
from regression.python_test_utils import test_utils
from regression.feature_utils.base_feature_test import BaseFeatureTest
+from .locators import QueryToolLocatorsCss
class QueryToolJourneyTest(BaseFeatureTest):
@@ -73,44 +74,51 @@ class QueryToolJourneyTest(BaseFeatureTest):
def _test_history_tab(self):
self.__clear_query_tool()
- editor_input = self.page.find_by_id("output-panel")
+ editor_input = self.page.find_by_css_selector(
+ QueryToolLocatorsCss.query_editor_panel)
self.page.click_element(editor_input)
self._execute_query("SELECT * FROM table_that_doesnt_exist")
self.page.click_tab("Query History")
selected_history_entry = self.page.find_by_css_selector(
- "#query_list .selected")
+ QueryToolLocatorsCss.query_history_selected)
self.assertIn("SELECT * FROM table_that_doesnt_exist",
selected_history_entry.text)
- failed_history_detail_pane = self.page.find_by_id("query_detail")
+
+ failed_history_detail_pane = self.page.find_by_css_selector(
+ QueryToolLocatorsCss.query_history_detail)
self.assertIn(
"Error Message relation \"table_that_doesnt_exist\" "
"does not exist", failed_history_detail_pane.text
)
- ActionChains(self.page.driver) \
- .send_keys(Keys.ARROW_DOWN) \
- .perform()
+ self.page.wait_for_element(lambda driver: driver
+ .find_element_by_css_selector
+ ("#query_list> .query-group>ul>li"))
+
+ # 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(
+ "#query_list> .query-group>ul>li")
+ print("the number of history_rows are 10 %s"%len(history_rows))
+ history_rows[1].click()
+
selected_history_entry = self.page.find_by_css_selector(
"#query_list .selected")
self.assertIn(("SELECT * FROM %s ORDER BY value" %
self.test_table_name),
selected_history_entry.text)
- query_element = self.page.driver.\
- find_element_by_xpath(
- "//div[@id='history_grid']//div[@class='entry selected']"
- "/div[@class='query']")
-
- self.assertIn(("SELECT * FROM %s ORDER BY value"
- % self.test_table_name), query_element.text)
-
+ # check second(invalid) query also exist in the history tab with error
newly_selected_history_entry = self.page.find_by_xpath(
- "//*[@id='query_list']/ul/li[2]")
+ "//*[@id='query_list']/div/ul/li[1]")
self.page.click_element(newly_selected_history_entry)
- selected_history_detail_pane = self.page.find_by_id("query_detail")
+
+ selected_invalid_history_entry = self.page.find_by_css_selector(
+ "#query_list .selected .entry.error .query")
+
self.assertIn("SELECT * FROM table_that_doesnt_exist",
- selected_history_detail_pane.get_attribute('innerHTML'))
+ selected_invalid_history_entry.text)
self.page.click_tab("Query Editor")
self.__clear_query_tool()
@@ -118,13 +126,14 @@ class QueryToolJourneyTest(BaseFeatureTest):
self.page.fill_codemirror_area_with("SELECT * FROM hats")
for _ in range(15):
- self.page.find_by_id("btn-flash").click()
+ self.page.find_by_css_selector(
+ QueryToolLocatorsCss.btn_execute_query).click()
self.page.wait_for_query_tool_loading_indicator_to_disappear()
self.page.click_tab("Query History")
query_we_need_to_scroll_to = self.page.find_by_xpath(
- "//*[@id='query_list']/ul/li[17]")
+ "//*[@id='query_list']/div/ul/li[17]")
self.page.click_element(query_we_need_to_scroll_to)
@@ -140,12 +149,13 @@ class QueryToolJourneyTest(BaseFeatureTest):
self.page.click_element(editor_input)
self.page.fill_codemirror_area_with("SELECT * FROM hats")
for _ in range(15):
- self.page.find_by_id("btn-flash").click()
+ self.page.find_by_css_selector(
+ QueryToolLocatorsCss.btn_execute_query).click()
self.page.wait_for_query_tool_loading_indicator_to_disappear()
self.page.click_tab("History")
query_we_need_to_scroll_to = self.page.find_by_xpath(
- "//*[@id='query_list']/ul/li[17]"
+ "//*[@id='query_list']/div/ul/li[17]"
)
for _ in range(17):
ActionChains(self.page.driver) \
@@ -173,7 +183,8 @@ class QueryToolJourneyTest(BaseFeatureTest):
def _execute_query(self, query):
self.page.fill_codemirror_area_with(query)
- self.page.find_by_id("btn-flash").click()
+ self.page.find_by_css_selector(
+ QueryToolLocatorsCss.btn_execute_query).click()
def _assert_clickable(self, element):
self.page.click_element(element)
diff --git a/web/pgadmin/feature_tests/query_tool_tests.py b/web/pgadmin/feature_tests/query_tool_tests.py
index c6e609cc..7f50f1e4 100644
--- a/web/pgadmin/feature_tests/query_tool_tests.py
+++ b/web/pgadmin/feature_tests/query_tool_tests.py
@@ -18,6 +18,7 @@ from selenium.webdriver.common.by import By
from regression.python_test_utils import test_utils
from regression.feature_utils.base_feature_test import BaseFeatureTest
import config
+from .locators import QueryToolLocatorsCss
class QueryToolFeatureTest(BaseFeatureTest):
@@ -110,28 +111,34 @@ class QueryToolFeatureTest(BaseFeatureTest):
# this will set focus to correct iframe.
self.page.fill_codemirror_area_with('')
- explain_op = self.page.find_by_id("btn-explain-options-dropdown")
+ explain_op = self.page.find_by_css_selector(
+ QueryToolLocatorsCss.btn_explain_options_dropdown)
explain_op.click()
# disable Explain options and auto rollback only if they are enabled.
- for op in ('explain-verbose', 'explain-costs',
- 'explain-buffers', 'explain-timing'):
- btn = self.page.find_by_id("btn-{}".format(op))
+ for op in (QueryToolLocatorsCss.btn_explain_verbose,
+ QueryToolLocatorsCss.btn_explain_costs,
+ QueryToolLocatorsCss.btn_explain_buffers,
+ QueryToolLocatorsCss.btn_explain_timing):
+ btn = self.page.find_by_css_selector(op)
check = btn.find_element_by_tag_name('i')
if 'visibility-hidden' not in check.get_attribute('class'):
btn.click()
- query_op = self.page.find_by_id("btn-query-dropdown")
+ query_op = self.page.find_by_css_selector(
+ QueryToolLocatorsCss.btn_query_dropdown)
query_op.click()
# disable auto rollback only if they are enabled
- btn = self.page.find_by_id("btn-auto-rollback")
+ btn = self.page.find_by_css_selector(
+ QueryToolLocatorsCss.btn_auto_rollback)
check = btn.find_element_by_tag_name('i')
if 'visibility-hidden' not in check.get_attribute('class'):
btn.click()
# enable autocommit only if it's disabled
- btn = self.page.find_by_id("btn-auto-commit")
+ btn = self.page.find_by_css_selector(
+ QueryToolLocatorsCss.btn_auto_commit)
check = btn.find_element_by_tag_name('i')
if 'visibility-hidden' in check.get_attribute('class'):
btn.click()
@@ -145,14 +152,14 @@ class QueryToolFeatureTest(BaseFeatureTest):
self.page.toggle_open_tree_item(self.test_db)
def _clear_query_tool(self):
- self.page.click_element(
- self.page.find_by_xpath("//*[@id='btn-clear-dropdown']")
+ self.page.click_element(self.page.find_by_css_selector(
+ QueryToolLocatorsCss.btn_clear_dropdown)
)
ActionChains(self.driver) \
- .move_to_element(self.page.find_by_xpath("//*[@id='btn-clear']")) \
- .perform()
+ .move_to_element(self.page.find_by_css_selector(
+ QueryToolLocatorsCss.btn_clear)).perform()
self.page.click_element(
- self.page.find_by_xpath("//*[@id='btn-clear']")
+ self.page.find_by_css_selector(QueryToolLocatorsCss.btn_clear)
)
self.page.click_modal('Yes')
@@ -171,7 +178,12 @@ SELECT generate_series(1, {}) as id1, 'dummy' as id2""".format(
wait = WebDriverWait(self.page.driver, 10)
self.page.fill_codemirror_area_with(query)
- self.page.find_by_id("btn-flash").click()
+ self.page.find_by_css_selector(
+ QueryToolLocatorsCss.btn_execute_query).click()
+
+ # wait for header of the table to be visible
+ wait.until(EC.visibility_of_element_located(
+ (By.XPATH,'//div[@class="slick-header-columns"]')))
wait.until(EC.presence_of_element_located(
(By.XPATH,
@@ -192,8 +204,13 @@ SELECT generate_series(1, {}) as id1, 'dummy' as id2""".format(
print("On demand result set on grid select all... ",
file=sys.stderr, end="")
- self.page.find_by_id("btn-flash").click()
+ self.page.find_by_css_selector(
+ QueryToolLocatorsCss.btn_execute_query).click()
+ # wait for header of the table to be visible
+ wait.until(EC.visibility_of_element_located(
+ (By.XPATH,'//div[@class="slick-header-columns"]')))
+ # wait for first row to contain value
wait.until(EC.presence_of_element_located(
(By.XPATH,
'//span[@data-row="0" and text()="1"]'))
@@ -210,10 +227,15 @@ SELECT generate_series(1, {}) as id1, 'dummy' as id2""".format(
print("On demand result set on column select all... ",
file=sys.stderr, end="")
- self.page.find_by_id("btn-flash").click()
+ self.page.find_by_css_selector(
+ QueryToolLocatorsCss.btn_execute_query).click()
self.page.wait_for_query_tool_loading_indicator_to_disappear()
+ # wait for header of the table to be visible
+ wait.until(EC.visibility_of_element_located(
+ (By.XPATH,'//div[@class="slick-header-columns"]')))
+
wait.until(EC.presence_of_element_located(
(By.XPATH,
'//span[@data-row="0" and text()="1"]'))
@@ -252,16 +274,19 @@ SELECT generate_series(1, 1000) as id order by id desc"""
self.page.fill_codemirror_area_with(query)
- explain_op = self.page.find_by_id("btn-explain-options-dropdown")
+ explain_op = self.page.find_by_css_selector(
+ QueryToolLocatorsCss.btn_explain_options_dropdown)
explain_op.click()
# disable Explain options and auto rollback only if they are enabled.
- for op in ('explain-verbose', 'explain-costs'):
- self.page.find_by_id("btn-{}".format(op)).click()
+ for op in (QueryToolLocatorsCss.btn_explain_verbose,
+ QueryToolLocatorsCss.btn_explain_costs):
+ self.page.find_by_css_selector(op).click()
explain_op.click()
- self.page.find_by_id("btn-explain").click()
+ self.page.find_by_css_selector(
+ QueryToolLocatorsCss.btn_explain).click()
self.page.wait_for_query_tool_loading_indicator_to_disappear()
@@ -285,16 +310,19 @@ SELECT generate_series(1, 1000) as id order by id desc"""
self.page.fill_codemirror_area_with(query)
- explain_op = self.page.find_by_id("btn-explain-options-dropdown")
+ explain_op = self.page.find_by_css_selector(
+ QueryToolLocatorsCss.btn_explain_options_dropdown)
explain_op.click()
# disable Explain options and auto rollback only if they are enabled.
- for op in ('explain-buffers', 'explain-timing'):
- self.page.find_by_id("btn-{}".format(op)).click()
+ for op in (QueryToolLocatorsCss.btn_explain_buffers,
+ QueryToolLocatorsCss.btn_explain_timing):
+ self.page.find_by_css_selector(op).click()
explain_op.click()
- self.page.find_by_id("btn-explain-analyze").click()
+ self.page.find_by_css_selector(
+ QueryToolLocatorsCss.btn_explain_analyze).click()
self.page.wait_for_query_tool_loading_indicator_to_disappear()
@@ -324,14 +352,18 @@ CREATE TABLE public.{}();""".format(table_name)
self.page.fill_codemirror_area_with(query)
- query_op = self.page.find_by_id("btn-query-dropdown")
+ # open auto commit option and disable it
+ query_op = self.page.find_by_css_selector(
+ QueryToolLocatorsCss.btn_query_dropdown)
query_op.click()
-
- self.page.find_by_id("btn-auto-commit").click()
-
+ self.page.find_by_css_selector(
+ QueryToolLocatorsCss.btn_auto_commit).click()
+ # close option
query_op.click()
- self.page.find_by_id("btn-flash").click()
+ # execute query
+ self.page.find_by_css_selector(
+ QueryToolLocatorsCss.btn_execute_query).click()
self.page.wait_for_query_tool_loading_indicator_to_disappear()
self.page.click_tab('Messages')
@@ -340,6 +372,7 @@ CREATE TABLE public.{}();""".format(table_name)
'contains(string(), "CREATE TABLE")]'
)
+ # do the ROLLBACK and check if the table is present or not
self._clear_query_tool()
query = """-- 1. (Done) Disable auto commit.
-- 2. (Done) Create table in public schema.
@@ -347,7 +380,8 @@ CREATE TABLE public.{}();""".format(table_name)
-- 4. Check if table is *NOT* created.
ROLLBACK;"""
self.page.fill_codemirror_area_with(query)
- self.page.find_by_id("btn-flash").click()
+ self.page.find_by_css_selector(
+ QueryToolLocatorsCss.btn_execute_query).click()
self.page.wait_for_query_tool_loading_indicator_to_disappear()
self.page.click_tab('Messages')
@@ -364,7 +398,8 @@ ROLLBACK;"""
SELECT relname FROM pg_class
WHERE relkind IN ('r','s','t') and relnamespace = 2200::oid;"""
self.page.fill_codemirror_area_with(query)
- self.page.find_by_id("btn-flash").click()
+ self.page.find_by_css_selector(
+ QueryToolLocatorsCss.btn_execute_query).click()
self.page.wait_for_query_tool_loading_indicator_to_disappear()
self.page.click_tab('Data Output')
@@ -379,6 +414,18 @@ SELECT relname FROM pg_class
"and without any explicit commit.".format(
table_name
)
+ # again roll back so that the auto commit drop down is enabled
+ query = """-- 1. (Done) Disable auto commit.
+ -- 2. (Done) Create table in public schema.
+ -- 3. ROLLBACK transaction.
+ -- 4. Check if table is *NOT* created.
+ ROLLBACK;"""
+ self.page.fill_codemirror_area_with(query)
+ self.page.find_by_css_selector(
+ QueryToolLocatorsCss.btn_execute_query).click()
+
+ self.page.wait_for_query_tool_loading_indicator_to_disappear()
+
def _query_tool_auto_commit_enabled(self):
@@ -393,14 +440,17 @@ END;"""
wait = WebDriverWait(self.page.driver, 10)
- query_op = self.page.find_by_id("btn-query-dropdown")
+ query_op = self.page.find_by_css_selector(
+ QueryToolLocatorsCss.btn_query_dropdown)
query_op.click()
- self.page.find_by_id("btn-auto-commit").click()
+ self.page.find_by_css_selector(
+ QueryToolLocatorsCss.btn_auto_commit).click()
query_op.click()
- self.page.find_by_id("btn-flash").click()
+ self.page.find_by_css_selector(
+ QueryToolLocatorsCss.btn_execute_query).click()
self.page.wait_for_query_tool_loading_indicator_to_disappear()
@@ -416,7 +466,8 @@ CREATE TABLE public.{}();""".format(table_name)
self.page.fill_codemirror_area_with(query)
- self.page.find_by_id("btn-flash").click()
+ self.page.find_by_css_selector(
+ QueryToolLocatorsCss.btn_execute_query).click()
self.page.wait_for_query_tool_loading_indicator_to_disappear()
self.page.click_tab('Messages')
@@ -433,7 +484,8 @@ CREATE TABLE public.{}();""".format(table_name)
-- 5. Check if table is created event after ROLLBACK.
ROLLBACK;"""
self.page.fill_codemirror_area_with(query)
- self.page.find_by_id("btn-flash").click()
+ self.page.find_by_css_selector(
+ QueryToolLocatorsCss.btn_execute_query).click()
self.page.wait_for_query_tool_loading_indicator_to_disappear()
self.page.click_tab('Messages')
@@ -451,7 +503,8 @@ ROLLBACK;"""
SELECT relname FROM pg_class
WHERE relkind IN ('r','s','t') and relnamespace = 2200::oid;"""
self.page.fill_codemirror_area_with(query)
- self.page.find_by_id("btn-flash").click()
+ self.page.find_by_css_selector(
+ QueryToolLocatorsCss.btn_execute_query).click()
self.page.click_tab('Data Output')
self.page.wait_for_query_tool_loading_indicator_to_disappear()
@@ -479,16 +532,18 @@ END;"""
self.page.fill_codemirror_area_with(query)
- query_op = self.page.find_by_id("btn-query-dropdown")
+ query_op = self.page.find_by_css_selector(
+ QueryToolLocatorsCss.btn_query_dropdown)
query_op.click()
- self.page.find_by_id("btn-auto-rollback").click()
-
- self.page.find_by_id("btn-auto-commit").click()
+ # uncheckt auto commit and check auto-rollback
+ self.uncheck_execute_option('auto_commit')
+ self.check_execute_option('auto_rollback')
query_op.click()
- self.page.find_by_id("btn-flash").click()
+ self.page.find_by_css_selector(
+ QueryToolLocatorsCss.btn_execute_query).click()
self.page.wait_for_query_tool_loading_indicator_to_disappear()
self._clear_query_tool()
@@ -504,7 +559,8 @@ CREATE TABLE public.{}();""".format(table_name)
self.page.fill_codemirror_area_with(query)
- self.page.find_by_id("btn-flash").click()
+ self.page.find_by_css_selector(
+ QueryToolLocatorsCss.btn_execute_query).click()
self.page.wait_for_query_tool_loading_indicator_to_disappear()
self.page.click_tab('Messages')
@@ -522,7 +578,8 @@ CREATE TABLE public.{}();""".format(table_name)
-- 6. Check if table is *NOT* created after ending transaction.
SELECT 1/0;"""
self.page.fill_codemirror_area_with(query)
- self.page.find_by_id("btn-flash").click()
+ self.page.find_by_css_selector(
+ QueryToolLocatorsCss.btn_execute_query).click()
self.page.wait_for_query_tool_loading_indicator_to_disappear()
self.page.click_tab('Messages')
@@ -541,7 +598,8 @@ SELECT 1/0;"""
END;"""
self.page.fill_codemirror_area_with(query)
- self.page.find_by_id("btn-flash").click()
+ self.page.find_by_css_selector(
+ QueryToolLocatorsCss.btn_execute_query).click()
self.page.wait_for_query_tool_loading_indicator_to_disappear()
self.page.click_tab('Messages')
@@ -560,7 +618,8 @@ END;"""
SELECT relname FROM pg_class
WHERE relkind IN ('r','s','t') and relnamespace = 2200::oid;"""
self.page.fill_codemirror_area_with(query)
- self.page.find_by_id("btn-flash").click()
+ self.page.find_by_css_selector(
+ QueryToolLocatorsCss.btn_execute_query).click()
self.page.wait_for_query_tool_loading_indicator_to_disappear()
self.page.click_tab('Data Output')
@@ -584,41 +643,27 @@ SELECT 1, pg_sleep(300)"""
self.page.fill_codemirror_area_with(query)
- query_op = self.page.find_by_id("btn-query-dropdown")
- query_op.click()
-
- auto_rollback_btn = self.page.find_by_id("btn-auto-rollback")
-
- auto_rollback_check = auto_rollback_btn.find_element_by_tag_name("i")
+ # query_button drop can be disabled so enable
+ commit_button = self.page.find_by_css_selector("#btn-commit")
+ if not commit_button.get_attribute('disabled'):
+ commit_button.click()
- # if auto rollback is enabled then 'i' element will
- # have 'auto-rollback fa fa-check' classes
- # if auto rollback is disabled then 'i' element will
- # have 'auto-rollback fa fa-check visibility-hidden' classes
-
- if 'auto-rollback fa fa-check' == str(
- auto_rollback_check.get_attribute('class')):
- auto_rollback_btn.click()
-
- auto_commit_btn = self.page.find_by_id("btn-auto-commit")
-
- auto_commit_check = auto_commit_btn.find_element_by_tag_name("i")
-
- # if auto commit is enabled then 'i' element will
- # have 'auto-commit fa fa-check' classes
- # if auto commit is disabled then 'i' element will
- # have 'auto-commit fa fa-check visibility-hidden' classes
-
- if 'auto-commit fa fa-check visibility-hidden' == str(
- auto_commit_check.get_attribute('class')):
- auto_commit_btn.click()
+ query_op = self.page.find_by_css_selector(
+ QueryToolLocatorsCss.btn_query_dropdown)
+ query_op.click()
+ # enable auto-commit and disable auto-rollback
+ self.check_execute_option('auto_commit')
+ self.uncheck_execute_option('auto_rollback')
+ # close drop down
query_op.click()
- self.page.find_by_id("btn-flash").click()
+ self.page.find_by_css_selector(
+ QueryToolLocatorsCss.btn_execute_query).click()
self.page.find_by_xpath("//*[@id='fetching_data']")
- self.page.find_by_id("btn-cancel-query").click()
+ self.page.find_by_css_selector(
+ QueryToolLocatorsCss.btn_cancel_query).click()
self.page.wait_for_query_tool_loading_indicator_to_disappear()
self.page.click_tab('Messages')
self.page.find_by_xpath(
@@ -643,7 +688,8 @@ SELECT 1, pg_sleep(300)"""
print("\n\tListen on an event... ", file=sys.stderr, end="")
self.page.fill_codemirror_area_with("LISTEN foo;")
- self.page.find_by_id("btn-flash").click()
+ self.page.find_by_css_selector(
+ QueryToolLocatorsCss.btn_execute_query).click()
self.page.wait_for_query_tool_loading_indicator_to_disappear()
self.page.click_tab('Messages')
@@ -656,7 +702,8 @@ SELECT 1, pg_sleep(300)"""
print("\tNotify event without data... ", file=sys.stderr, end="")
self.page.fill_codemirror_area_with("NOTIFY foo;")
- self.page.find_by_id("btn-flash").click()
+ self.page.find_by_css_selector(
+ QueryToolLocatorsCss.btn_execute_query).click()
self.page.wait_for_query_tool_loading_indicator_to_disappear()
self.page.click_tab('Notifications')
@@ -670,7 +717,8 @@ SELECT 1, pg_sleep(300)"""
if self._supported_server_version():
self.page.fill_codemirror_area_with("SELECT pg_notify('foo', "
"'Hello')")
- self.page.find_by_id("btn-flash").click()
+ self.page.find_by_css_selector(
+ QueryToolLocatorsCss.btn_execute_query).click()
self.page.wait_for_query_tool_loading_indicator_to_disappear()
self.page.click_tab('Notifications')
@@ -690,39 +738,62 @@ SELECT 1, pg_sleep(300)"""
self.server['port'],
self.server['sslmode']
)
-
pg_cursor = connection.cursor()
pg_cursor.execute('select version()')
version_string = pg_cursor.fetchone()
+ # check if jit is turned on
+ jit_enabled = False
+ try:
+ pg_cursor.execute('show jit')
+ show_jit = pg_cursor.fetchone()
+ if show_jit[0] == 'on':
+ jit_enabled = True
+ except:
+ pass
+
is_edb = False
if len(version_string) > 0:
is_edb = 'EnterpriseDB' in version_string[0]
connection.close()
- return connection.server_version >= 110000 and not is_edb
+ return connection.server_version >= 110000 and jit_enabled
def _query_tool_explain_check_jit_stats(self):
wait = WebDriverWait(self.page.driver, 10)
self.page.fill_codemirror_area_with("SET jit_above_cost=10;")
- self.page.find_by_id("btn-flash").click()
+ self.page.find_by_css_selector(
+ QueryToolLocatorsCss.btn_execute_query).click()
self.page.wait_for_query_tool_loading_indicator_to_disappear()
self._clear_query_tool()
self.page.fill_codemirror_area_with("SELECT count(*) FROM pg_class;")
- explain_op = self.page.find_by_id("btn-explain-options-dropdown")
+ explain_op = self.page.find_by_css_selector(
+ QueryToolLocatorsCss.btn_explain_options_dropdown)
explain_op.click()
- # disable Explain options and auto rollback only if they are enabled.
- for op in ('explain-verbose', 'explain-costs', 'explain-analyze'):
- self.page.find_by_id("btn-{}".format(op)).click()
+ # disable Explain options and only enable COST option
+ for op in (QueryToolLocatorsCss.btn_explain_verbose,
+ QueryToolLocatorsCss.btn_explain_costs,
+ QueryToolLocatorsCss.btn_explain_buffers,
+ QueryToolLocatorsCss.btn_explain_timing):
+ btn = self.page.find_by_css_selector(op)
+ check = btn.find_element_by_tag_name('i')
+ if 'visibility-hidden' not in check.get_attribute('class'):
+ btn.click()
+ # click cost button
+ cost_btn = self.page.find_by_css_selector(
+ QueryToolLocatorsCss.btn_explain_costs)
+ cost_btn.click()
+ # close explain options
explain_op.click()
- self.page.find_by_id("btn-explain-analyze").click()
+ self.page.find_by_css_selector(
+ QueryToolLocatorsCss.btn_explain_analyze).click()
self.page.wait_for_query_tool_loading_indicator_to_disappear()
self.page.click_tab('Data Output')
@@ -735,6 +806,38 @@ SELECT 1, pg_sleep(300)"""
self._clear_query_tool()
+ def check_execute_option(self, option):
+ """"This function will check auto commit or auto roll back based on
+ user input. If button is already checked, no action will be taken"""
+ if option == 'auto_commit':
+ check_status = self.driver.find_element_by_css_selector(
+ QueryToolLocatorsCss.btn_auto_commit_check_status)
+ if 'visibility-hidden' in check_status.get_attribute('class'):
+ self.page.find_by_css_selector(QueryToolLocatorsCss.
+ btn_auto_commit).click()
+ if option == 'auto_rollback':
+ check_status = self.driver.find_element_by_css_selector(
+ QueryToolLocatorsCss.btn_auto_rollback_check_status)
+ if 'visibility-hidden' in check_status.get_attribute('class'):
+ self.page.find_by_css_selector(QueryToolLocatorsCss.
+ btn_auto_rollback).click()
+
+ def uncheck_execute_option(self, option):
+ """"This function will uncheck auto commit or auto roll back based on
+ user input. If button is already unchecked, no action will be taken"""
+ if option == 'auto_commit':
+ check_status = self.driver.find_element_by_css_selector(
+ QueryToolLocatorsCss.btn_auto_commit_check_status)
+ if 'visibility-hidden' not in check_status.get_attribute('class'):
+ self.page.find_by_css_selector(QueryToolLocatorsCss.
+ btn_auto_commit).click()
+ if option == 'auto_rollback':
+ check_status = self.driver.find_element_by_css_selector(
+ QueryToolLocatorsCss.btn_auto_rollback_check_status)
+ if 'visibility-hidden' not in check_status.get_attribute('class'):
+ self.page.find_by_css_selector(QueryToolLocatorsCss.
+ btn_auto_rollback).click()
+
class WaitForAnyElementWithText(object):
def __init__(self, locator, text):
diff --git a/web/pgadmin/feature_tests/test_data.json b/web/pgadmin/feature_tests/test_data.json
index 03aca9aa..50374c6c 100644
--- a/web/pgadmin/feature_tests/test_data.json
+++ b/web/pgadmin/feature_tests/test_data.json
@@ -9,7 +9,7 @@
"6": ["\\\"\\\"", "\"\"", "text", "double backslash followed by a double quote"],
"7": ["\\\\\"\\\\\"", "\\\\\"\\\\\"", "text", "double backslash followed by a double quote"],
"8": ["", "[null]", "text"],
- "9": ["", "[51,52]", "json"],
+ "9": ["", "[51, 52]", "json"],
"10": ["[61,62]", "[61,62]", "json"],
"11": ["", "true", "bool"],
"12": ["", "[null]", "bool"],
@@ -18,7 +18,7 @@
"15": ["{}", "{}", "text[]"],
"16": ["{data,NULL,'',\"\"}", "{data,NULL,'',\"\"}", "text[]"],
"17": ["{}", "{}", "int[]"],
- "18": ["{123,,456}", "{123,NULL,456}", "int[]"],
+ "18": ["{123,123,456}", "{123,123,456}", "int[]"],
"19": ["", "[null]", "boolean[]"],
"20": ["{false,null,true}", "{f,NULL,t}", "boolean[]"]
}
diff --git a/web/pgadmin/feature_tests/view_data_dml_queries.py b/web/pgadmin/feature_tests/view_data_dml_queries.py
index 1be9dcfa..8e69ffc5 100644
--- a/web/pgadmin/feature_tests/view_data_dml_queries.py
+++ b/web/pgadmin/feature_tests/view_data_dml_queries.py
@@ -109,7 +109,7 @@ CREATE TABLE public.defaults_{0}
for cnt in (1, 2):
self.page.select_tree_item('defaults_{0}'.format(str(cnt)))
# Open Object -> View/Edit data
- self._view_data_grid()
+ self._view_data_grid('defaults_{0}'.format(str(cnt)))
self.page.wait_for_query_tool_loading_indicator_to_disappear()
# Run test to insert a new row in table with default values
@@ -182,15 +182,15 @@ CREATE TABLE public.defaults_{0}
cell_el.find_element_by_css_selector('input').clear()
else:
ActionChains(self.driver).send_keys(value).perform()
-
elif cell_type in ['text', 'json', 'text[]', 'boolean[]']:
- self.page.find_by_xpath(
- "//*[contains(@class, 'pg_textarea')]").click()
- ActionChains(self.driver).send_keys(value).perform()
+ text_area_ele = self.page.find_by_css_selector(
+ ".pg-text-editor > textarea")
+ text_area_ele.click()
+ text_area_ele.send_keys(value)
# Click on editor's Save button
self.page.find_by_css_selector(
- '.pg_text_editor button[data-label="Save"]').click()
+ '.btn.btn-primary.long_text_editor').click()
else:
# Boolean editor test for to True click
if data[1] == 'true':
@@ -214,7 +214,7 @@ CREATE TABLE public.defaults_{0}
self.page.toggle_open_tree_item('public')
self.page.toggle_open_tree_item('Tables')
- def _view_data_grid(self):
+ def _view_data_grid(self, table_name):
self.page.driver.find_element_by_link_text("Object").click()
ActionChains(
self.page.driver
@@ -224,7 +224,8 @@ CREATE TABLE public.defaults_{0}
self.page.find_by_partial_link_text("All Rows").click()
time.sleep(1)
# wait until datagrid frame is loaded.
- self.page.click_tab('Edit Data -')
+
+ self.page.click_tab(table_name)
self.wait.until(
EC.visibility_of_element_located(
@@ -309,6 +310,7 @@ CREATE TABLE public.defaults_{0}
if (idx != 1 and not is_new_row) or is_new_row:
self.assertEquals(element.text, config_data[str(idx)][1])
+ self.assertEquals(element.text, config_data[str(idx)][1])
# scroll browser back to the left
# to reset position so other assertions can succeed
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 27ac8c2c..8175bf9f 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
@@ -52,13 +52,21 @@ class CheckForXssFeatureTest(BaseFeatureTest):
self._check_xss_in_browser_tree()
self._check_xss_in_properties_tab()
self._check_xss_in_sql_tab()
+
+ # sometime the tab for dependent does not show info, so refreshing
+ # the page and then again collapsing until the table node
+ self.page.refresh_page()
+ self.page.toggle_open_servers_group()
+ self._tables_node_expandable()
self._check_xss_in_dependents_tab()
# Query tool
+ self.page.open_query_tool()
self._check_xss_in_query_tool()
self.page.close_query_tool()
# Explain module
+ self.page.open_query_tool()
self._check_xss_in_explain_module()
self.page.close_query_tool()
@@ -125,6 +133,7 @@ class CheckForXssFeatureTest(BaseFeatureTest):
# Create any constraint with xss name to test this
def _check_xss_in_dependents_tab(self):
+
print(
"\n\tChecking the Dependents tab for the XSS",
file=sys.stderr, end=""
@@ -142,17 +151,11 @@ class CheckForXssFeatureTest(BaseFeatureTest):
"Dependents tab (BackGrid)"
)
- def _open_query_tool(self):
- self.page.driver.find_element_by_link_text("Tools").click()
- self.page.find_by_partial_link_text("Query Tool").click()
- self.page.click_tab('Query -')
-
def _check_xss_in_query_tool(self):
print(
"\n\tChecking the SlickGrid cell for the XSS",
file=sys.stderr, end=""
)
- self._open_query_tool()
self.page.fill_codemirror_area_with(
"select '

'"
)
@@ -179,14 +182,10 @@ class CheckForXssFeatureTest(BaseFeatureTest):
"\n\tChecking the Graphical Explain plan for the XSS ...",
file=sys.stderr, end=""
)
- self._open_query_tool()
self.page.fill_codemirror_area_with(
'select * from "{0}"'.format(self.test_table_name)
)
- query_op = self.page.find_by_id("btn-query-dropdown")
- query_op.click()
-
self.page.find_by_id("btn-explain").click()
self.page.wait_for_query_tool_loading_indicator_to_disappear()
self.page.click_tab('Explain')
diff --git a/web/pgadmin/tools/datagrid/static/js/datagrid.js b/web/pgadmin/tools/datagrid/static/js/datagrid.js
index 912c99be..b22034e0 100644
--- a/web/pgadmin/tools/datagrid/static/js/datagrid.js
+++ b/web/pgadmin/tools/datagrid/static/js/datagrid.js
@@ -54,14 +54,7 @@ define('pgadmin.datagrid', [
self.preferences = pgBrowser.get_preferences_for_module('sqleditor');
});
- this.spinner_el =
- `
`;
+
// Define list of nodes on which view data option appears
var supported_nodes = [
'table', 'view', 'mview',
@@ -518,17 +511,26 @@ define('pgadmin.datagrid', [
var openQueryToolURL = function(j) {
// add spinner element
- $(j).data('embeddedFrame').$container.append(pgAdmin.DataGrid.spinner_el);
- setTimeout(function() {
+ let $spinner_el =
+ $(`
`).appendTo($(j).data('embeddedFrame').$container);
+
+ let init_poller_id = setInterval(function() {
var frameInitialized = $(j).data('frameInitialized');
if (frameInitialized) {
+ clearInterval(init_poller_id);
var frame = $(j).data('embeddedFrame');
if (frame) {
+ frame.onLoaded(()=>{
+ $spinner_el.remove();
+ });
frame.openURL(baseUrl);
- frame.$container.find('.pg-sp-container').delay(1000).hide(1);
}
- } else {
- openQueryToolURL(j);
}
}, 100);
};
diff --git a/web/pgadmin/utils/route.py b/web/pgadmin/utils/route.py
index e67f0195..b206cb2e 100644
--- a/web/pgadmin/utils/route.py
+++ b/web/pgadmin/utils/route.py
@@ -53,7 +53,7 @@ class TestsGeneratorRegistry(ABCMeta):
ABCMeta.__init__(cls, name, bases, d)
@classmethod
- def load_generators(cls, pkg_root, exclude_pkgs):
+ def load_generators(cls, pkg_root, exclude_pkgs, for_modules=[]):
cls.registry = dict()
@@ -61,6 +61,13 @@ class TestsGeneratorRegistry(ABCMeta):
all_modules += find_modules(pkg_root, False, True)
+ # If specific modules are to be tested, exclude others
+ if len(for_modules) > 0:
+ all_modules = [module_name
+ for module_name in all_modules
+ for fmod in for_modules
+ if module_name.endswith(fmod)]
+
# Check for SERVER mode
for module_name in all_modules:
try:
diff --git a/web/regression/README b/web/regression/README
index 7e668cfd..6a68d36f 100644
--- a/web/regression/README
+++ b/web/regression/README
@@ -167,6 +167,14 @@ Python Tests:
Example 2) Run test framework for 'database' node
run 'python runtests.py --pkg browser.server_groups.servers.databases.tests'
+- Execute test framework for certain modules of a test pkg
+
+ Example 1) Run test framework for 'sqleditor' package and test_start_running_query module
+ run 'python runtests.py --pkg tools.sqleditor --modules test_start_running_query'
+
+ Example 2) Run test framework for 'sqleditor' package and test_start_running_query,test_query_tool_fs_utils modules
+ run 'python runtests.py --pkg tools.sqleditor --modules test_start_running_query,test_query_tool_fs_utils'
+
- Exclude a package and its subpackages when running tests:
Example: exclude feature tests but run all others:
diff --git a/web/regression/feature_utils/pgadmin_page.py b/web/regression/feature_utils/pgadmin_page.py
index 0c8f0fa3..e09ceac1 100644
--- a/web/regression/feature_utils/pgadmin_page.py
+++ b/web/regression/feature_utils/pgadmin_page.py
@@ -10,7 +10,8 @@
import time
from selenium.common.exceptions import NoSuchElementException, \
- WebDriverException, TimeoutException, NoSuchWindowException
+ WebDriverException, TimeoutException, NoSuchWindowException, \
+ StaleElementReferenceException
from selenium.webdriver import ActionChains
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.support import expected_conditions as EC
@@ -93,7 +94,6 @@ class PgadminPage:
self.enable_menu_item(query_tool, 10)
self.find_by_partial_link_text("Query Tool").click()
- self.click_tab('Query -')
def enable_menu_item(self, menu_item, wait_time):
start_time = time.time()
@@ -110,11 +110,10 @@ class PgadminPage:
else:
assert False, "'Tools -> Query Tool' menu did not enable."
- def close_query_tool(self, name="Query", prompt=True):
+ def close_query_tool(self, prompt=True):
self.driver.switch_to.default_content()
tab = self.find_by_xpath(
- "//*[contains(@class,'wcPanelTab') and "
- "contains(.,'" + name + "')]")
+ "//div[@class='wcPanelTab wcPanelTabActive']")
ActionChains(self.driver).context_click(tab).perform()
self.find_by_xpath(
"//li[contains(@class, 'context-menu-item')]/span[contains(text(),"
@@ -149,18 +148,54 @@ class PgadminPage:
def select_tree_item(self, tree_item_text):
item = self.find_by_xpath(
- "//*[@id='tree']//*[.='" + tree_item_text +
- "' and @class='aciTreeItem']")
+ "//*[@id='tree']//*[contains(text(), '" + tree_item_text + "')]"
+ "/parent::span[@class='aciTreeItem']")
self.driver.execute_script("arguments[0].scrollIntoView()", item)
item.click()
- def toggle_open_tree_item(self, tree_item_text):
- item = self.find_by_xpath(
- "//*[@id='tree']//*[.='" + tree_item_text +
- "']/../*[@class='aciTreeButton']")
+ def toggle_open_servers_group(self):
+ """This will open Servers group to display underlying nodes"""
+ self.wait_for_spinner_to_disappear()
+ server_group = self.find_by_xpath(
+ "//div[@id='tree']//span[@class='aciTreeItem']"
+ "/span[(@class='aciTreeText') and starts-with(text(),'Servers ') "
+ "or starts-with(text(), 'Servers')]")
+ ActionChains(self.driver).double_click(server_group).perform()
- self.driver.execute_script("arguments[0].scrollIntoView()", item)
- item.click()
+ 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
+ # even if the underlying node to be clicked was Opened.
+ time.sleep(.6)
+ item_with_text = self.find_by_xpath(
+ "//div[@id='tree']//span[@class='aciTreeItem']/span["
+ "(@class='aciTreeText') and text()='" + tree_item_text + "']")
+
+ self.driver.execute_script("arguments[0].scrollIntoView()",
+ item_with_text)
+
+ if item_with_text.find_element_by_xpath(
+ ".//ancestor::*[@class='aciTreeLine']").get_attribute(
+ "aria-expanded") == 'false':
+ item = item_with_text.find_element_by_xpath(
+ ".//parent::*[@class='aciTreeItem']")
+ ActionChains(self.driver).double_click(item).perform()
+
+ def toggle_open_tables_node(self):
+ """The function will be used for opening Trees node only"""
+
+ # get the element which contains 'aria-expanded' info
+ tables_expansion_ele =self.find_by_xpath("//div[div[div[div[div[div"
+ "[div[div[span[span["
+ "(@class='aciTreeText') and "
+ "text()='Tables']]]]]]]]]]")
+
+ if tables_expansion_ele.get_attribute('aria-expanded') =='false':
+ # button element of the Tables node to open it
+ item_button = self.find_by_xpath(
+ "//div[span[span[(@class='aciTreeText') and text()"
+ "='Tables']]]/span[@class='aciTreeButton']")
+ ActionChains(self.driver).click(item_button).perform()
def toggle_open_server(self, tree_item_text):
def check_for_password_dialog_or_tree_open(driver):
@@ -224,38 +259,103 @@ class PgadminPage:
"clicking the element not to throw an exception", click_succeeded
)
- def fill_input_by_field_name(self, field_name, field_content):
- field = self.find_by_xpath("//input[@name='" + field_name + "']")
- backspaces = [Keys.BACKSPACE] * len(field.get_attribute('value'))
+ def js_send_key(self, field, sele_key):
+ keycode = None
+
+ if sele_key in (Keys.RETURN, Keys.ENTER):
+ keycode = 13
+ elif sele_key == Keys.ARROW_DOWN:
+ keycode = 40
+ self.driver.execute_script(
+ "arguments[0].dispatchEvent(new KeyboardEvent('keydown', "
+ "{'keyCode':arguments[1], 'which':arguments[1]}));"
+ "arguments[0].dispatchEvent(new KeyboardEvent('keypress', "
+ "{'keyCode':arguments[1], 'which':arguments[1]}));"
+ "arguments[0].dispatchEvent(new KeyboardEvent('keyup', "
+ "{'keyCode':arguments[1], 'which':arguments[1]}));"
+ "arguments[0].dispatchEvent(new Event('input'));"
+ "arguments[0].dispatchEvent(new Event('change'));",
+ field, keycode)
+
+ def js_loose_focus(self, field):
+ self.driver.execute_script(
+ "arguments[0].dispatchEvent(new Event('blur'));", field)
+
+ def fill_input(self, field, field_content, input_keys=False,
+ key_after_input=Keys.ARROW_DOWN):
field.click()
- field.send_keys(backspaces)
- field.send_keys(str(field_content))
- self.wait_for_input_field_content(field_name, field_content)
- def fill_codemirror_area_with(self, field_content):
+ # Use send keys if input_keys true, else use javascript to set content
+ if input_keys:
+ backspaces = [Keys.BACKSPACE] * len(field.get_attribute('value'))
+ field.send_keys(backspaces)
+ field.send_keys(str(field_content))
+ self.wait_for_input_by_element(field, field_content)
+ else:
+ self.driver.execute_script("arguments[0].value = arguments[1]",
+ field, field_content)
+ # keycode 40 is for arrow down
+ self.js_send_key(field, Keys.ARROW_DOWN)
+
+ if key_after_input:
+ self.js_send_key(field, key_after_input)
+
+ def fill_input_by_field_name(self, field_name, field_content,
+ input_keys=False,
+ key_after_input=Keys.ARROW_DOWN,
+ loose_focus=False):
+ field = self.find_by_css_selector(
+ "input[name='" + field_name + "']:not(:disabled)")
+ self.fill_input(field, field_content, input_keys=input_keys,
+ key_after_input=key_after_input)
+
+ if loose_focus:
+ self.js_loose_focus(field)
+
+ def fill_input_by_css_selector(self, css_selector, field_content,
+ input_keys=False,
+ key_after_input=Keys.ARROW_DOWN,
+ loose_focus=False):
+ field = self.find_by_css_selector(css_selector)
+ self.fill_input(field, field_content, input_keys=input_keys,
+ key_after_input=key_after_input)
+
+ if loose_focus:
+ self.js_loose_focus(field)
+
+ def fill_codemirror_area_with(self, field_content, input_keys=False):
def find_codemirror(driver):
try:
driver.switch_to.default_content()
driver.switch_to_frame(
driver.find_element_by_tag_name("iframe"))
- element = driver.find_element_by_xpath(
- "//pre[contains(@class,'CodeMirror-line')]/../../../"
- "*[contains(@class,'CodeMirror-code')]")
+ element = driver.find_element_by_css_selector(
+ "#output-panel .CodeMirror")
if element.is_displayed() and element.is_enabled():
return element
except (NoSuchElementException, WebDriverException):
return False
+ codemirror_ele = WebDriverWait(
+ self.driver, timeout=self.timeout, poll_frequency=0.01)\
+ .until(find_codemirror,
+ "Timed out waiting for codemirror to appear")
+
time.sleep(1)
- WebDriverWait(self.driver, timeout=self.timeout, poll_frequency=0.01).\
- until(find_codemirror, "Timed out waiting for codemirror "
- "to appear").click()
- time.sleep(1)
+ codemirror_ele.click()
- action = ActionChains(self.driver)
- action.send_keys(field_content)
- action.perform()
+ # Use send keys if input_keys true, else use javascript to set content
+ if input_keys:
+ action = ActionChains(self.driver)
+ action.send_keys(field_content)
+ action.perform()
+ else:
+ self.driver.execute_script(
+ "arguments[0].CodeMirror.setValue(arguments[1]);"
+ "arguments[0].CodeMirror.setCursor("
+ "arguments[0].CodeMirror.lineCount(),0);",
+ codemirror_ele, field_content)
def click_tab(self, tab_name):
WebDriverWait(self.driver, 10).until(EC.element_to_be_clickable(
@@ -269,7 +369,15 @@ class PgadminPage:
self.click_element(tab)
- def wait_for_input_field_content(self, field_name, content):
+ def wait_for_input_by_element(self, element, content):
+ def input_field_has_content(driver):
+ return str(content) == element.get_attribute('value')
+
+ return self._wait_for(
+ "field to contain '" + str(content) + "'", input_field_has_content
+ )
+
+ def wait_for_input_field_content(self, field_name, content, wait=1):
def input_field_has_content(driver):
element = driver.find_element_by_xpath(
"//input[@name='" + field_name + "']")
@@ -277,8 +385,20 @@ class PgadminPage:
return str(content) == element.get_attribute('value')
return self._wait_for(
- "field to contain '" + str(content) + "'", input_field_has_content
- )
+ "field to contain '" + str(content) + "'", input_field_has_content,
+ wait)
+
+ def check_if_element_exist_by_xpath(self, xpath, timeout=5):
+ """This function will verify if an element exist and on that basis
+ will return True or False. Will handle exception internally"""
+ element_found = False
+ try:
+ WebDriverWait(self.driver, timeout, .01).until(
+ EC.visibility_of_element_located((By.XPATH, xpath)))
+ element_found = True
+ except:
+ pass
+ return element_found
def wait_for_element(self, find_method_with_args):
def element_if_it_exists(driver):
@@ -286,7 +406,7 @@ class PgadminPage:
element = find_method_with_args(driver)
if element.is_displayed() and element.is_enabled():
return True
- except NoSuchElementException:
+ except (NoSuchElementException, StaleElementReferenceException):
return False
self._wait_for("element to exist", element_if_it_exists)
@@ -329,10 +449,10 @@ class PgadminPage:
def wait_for_query_tool_loading_indicator_to_disappear(self):
def spinner_has_disappeared(driver):
try:
- driver.find_element_by_xpath(
- "//*[@id='fetching_data' and @class='hide']"
+ spinner = driver.find_element_by_css_selector(
+ "#editor-panel .pg-sp-container"
)
- return False
+ return "d-none" in spinner.get_attribute("class")
except NoSuchElementException:
# wait for loading indicator disappear animation to complete.
time.sleep(0.5)
diff --git a/web/regression/python_test_utils/test_gui_helper.py b/web/regression/python_test_utils/test_gui_helper.py
index b1d3b25f..2e8bffcb 100644
--- a/web/regression/python_test_utils/test_gui_helper.py
+++ b/web/regression/python_test_utils/test_gui_helper.py
@@ -17,22 +17,18 @@ def close_bgprocess_popup(tester):
# In cases where backup div is not closed (sometime due to some error)
try:
if tester.driver.find_element_by_css_selector(
- ".ajs-message.ajs-bg-bgprocess.ajs-visible > div > "
- "div > div > i"):
+ ".ajs-message.ajs-bg-bgprocess.ajs-visible"):
tester.driver.find_element_by_css_selector(
- ".ajs-message.ajs-bg-bgprocess.ajs-visible >div >div "
- ">div>i").click()
+ ".btn.btn-sm-sq.btn-primary.pg-bg-close > i").click()
except Exception:
pass
# In cases where restore div is not closed (sometime due to some error)
try:
if tester.driver.find_element_by_xpath(
- "//div[contains(text(), 'Process Watcher - "
- "Restoring backup')]"):
- tester.driver.find_element_by_xpath(
- "//div[div[div[div[contains(text(), 'Process Watcher "
- "- Restoring backup')]]]]"
- "/following-sibling::div/div/div").click()
+ "//div[@class='card-header bg-primary d-flex']/div[contains("
+ "text(), 'Restoring backup')]"):
+ tester.driver.find_element_by_css_selector(
+ ".btn.btn-sm-sq.btn-primary.pg-bg-close > i").click()
except Exception:
pass
diff --git a/web/regression/requirements.txt b/web/regression/requirements.txt
index 5199d32d..9093a3d0 100644
--- a/web/regression/requirements.txt
+++ b/web/regression/requirements.txt
@@ -16,7 +16,7 @@ python-mimeparse==1.6.0
testscenarios==0.5.0
testtools==2.3.0
traceback2==1.4.0
-selenium==3.11.0
+selenium==3.14.0
###############################################################
# Modules specifically required for Python3.3 or lesser version
@@ -25,4 +25,4 @@ mock===2.0.0; python_version < '3.3'
# Leave this at the end because there is a bug where the '--install-option'
# is applied to all subsequent requirements
-chromedriver_installer==0.0.6 --install-option='--chromedriver-version=2.45'
+chromedriver_installer==0.0.6 --install-option='--chromedriver-version=2.46'
diff --git a/web/regression/runtests.py b/web/regression/runtests.py
index f757decb..92b86e0f 100644
--- a/web/regression/runtests.py
+++ b/web/regression/runtests.py
@@ -230,9 +230,14 @@ def get_test_modules(arguments):
if arguments['pkg'] is None or arguments['pkg'] == "all":
TestsGeneratorRegistry.load_generators('pgadmin', exclude_pkgs)
else:
+ for_modules = []
+ if arguments['modules'] is not None:
+ for_modules = arguments['modules'].split(',')
+
TestsGeneratorRegistry.load_generators('pgadmin.%s' %
arguments['pkg'],
- exclude_pkgs)
+ exclude_pkgs,
+ for_modules)
# Sort module list so that test suite executes the test cases sequentially
module_list = TestsGeneratorRegistry.registry.items()
@@ -263,6 +268,10 @@ def add_arguments():
'--default_browser',
help='Executes the feature test in specific browser'
)
+ parser.add_argument(
+ '--modules',
+ help='Executes the feature test for specific modules in pkg'
+ )
arg = parser.parse_args()
return arg