');
myPanel.layout().addItem($frameArea);
that.panel = myPanel;
var frame = new wcIFrame($frameArea, myPanel);
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..34aea87c
--- /dev/null
+++ b/web/pgadmin/feature_tests/locators.py
@@ -0,0 +1,21 @@
+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_commit = "#btn-auto-commit"
+ 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_utilities_backup_restore_test.py b/web/pgadmin/feature_tests/pg_utilities_backup_restore_test.py
index 1c89393d..c98e2fba 100644
--- a/web/pgadmin/feature_tests/pg_utilities_backup_restore_test.py
+++ b/web/pgadmin/feature_tests/pg_utilities_backup_restore_test.py
@@ -69,7 +69,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-save') "
"and contains(.,'Backup')]").click()
@@ -83,6 +84,7 @@ class PGUtilitiesBackupFeatureTest(BaseFeatureTest):
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 +101,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 +118,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()
diff --git a/web/pgadmin/feature_tests/query_tool_journey_test.py b/web/pgadmin/feature_tests/query_tool_journey_test.py
index d863f8e8..670de66f 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,16 +74,18 @@ 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\" "
@@ -108,7 +111,8 @@ class QueryToolJourneyTest(BaseFeatureTest):
newly_selected_history_entry = self.page.find_by_xpath(
"//*[@id='query_list']/ul/li[2]")
self.page.click_element(newly_selected_history_entry)
- selected_history_detail_pane = self.page.find_by_id("query_detail")
+ selected_history_detail_pane = self.page.find_by_css_selector(
+ QueryToolLocatorsCss.query_history_detail)
self.assertIn("SELECT * FROM table_that_doesnt_exist",
selected_history_detail_pane.get_attribute('innerHTML'))
@@ -118,7 +122,8 @@ 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")
@@ -140,7 +145,8 @@ 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")
@@ -173,7 +179,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..3372ccf9 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,8 @@ 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.until(EC.presence_of_element_located(
(By.XPATH,
@@ -192,7 +200,8 @@ 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.until(EC.presence_of_element_located(
(By.XPATH,
@@ -210,7 +219,8 @@ 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()
@@ -252,16 +262,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 +298,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 +340,17 @@ CREATE TABLE public.{}();""".format(table_name)
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-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()
self.page.click_tab('Messages')
@@ -347,7 +366,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 +384,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')
@@ -393,14 +414,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 +440,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 +458,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 +477,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 +506,20 @@ 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_css_selector(
+ QueryToolLocatorsCss.btn_auto_rollback).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()
self._clear_query_tool()
@@ -504,7 +535,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 +554,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 +574,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 +594,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,10 +619,12 @@ SELECT 1, pg_sleep(300)"""
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()
- auto_rollback_btn = self.page.find_by_id("btn-auto-rollback")
+ auto_rollback_btn = self.page.find_by_css_selector(
+ QueryToolLocatorsCss.btn_auto_commit)
auto_rollback_check = auto_rollback_btn.find_element_by_tag_name("i")
@@ -600,7 +637,8 @@ SELECT 1, pg_sleep(300)"""
auto_rollback_check.get_attribute('class')):
auto_rollback_btn.click()
- auto_commit_btn = self.page.find_by_id("btn-auto-commit")
+ auto_commit_btn = self.page.find_by_css_selector(
+ QueryToolLocatorsCss.btn_auto_commit)
auto_commit_check = auto_commit_btn.find_element_by_tag_name("i")
@@ -615,10 +653,12 @@ SELECT 1, pg_sleep(300)"""
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 +683,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 +697,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 +712,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')
@@ -707,22 +750,26 @@ SELECT 1, pg_sleep(300)"""
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()
+ 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-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')
diff --git a/web/pgadmin/feature_tests/view_data_dml_queries.py b/web/pgadmin/feature_tests/view_data_dml_queries.py
index 1be9dcfa..3c00d571 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
@@ -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 0a795fab..4ed072b6 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',
@@ -525,17 +518,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..72fbd356 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,37 @@ 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(.3)
+ 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_server(self, tree_item_text):
def check_for_password_dialog_or_tree_open(driver):
@@ -224,38 +242,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 +352,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 +368,8 @@ 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 wait_for_element(self, find_method_with_args):
def element_if_it_exists(driver):
@@ -286,7 +377,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 +420,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/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 48d3749f..6f95370f 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