mirror of
https://github.com/pgadmin-org/pgadmin4.git
synced 2025-01-09 07:33:19 -06:00
Many fixes to the stability of the feature tests, including:
tree toggle issue Query tool inteliSence issue eg. when there is only one option and drop down is not shown Backup and restore windows locator changes Fixes required due to resolving rm # 4041 Dependent tab not showing data sometime, so refreshed the page and handled it Due to change of logic for auto commit, did the required changes Due to fix of RM 4062, did the required workaround which broke the test case.
This commit is contained in:
parent
3f22503ad2
commit
be26fc540c
@ -53,7 +53,7 @@ define([
|
||||
|
||||
myPanel.closeable(!!that.isCloseable);
|
||||
|
||||
var $frameArea = $('<div style="position:absolute;top:0 !important;width:100%;height:100%;display:table">');
|
||||
var $frameArea = $('<div style="position:absolute;top:0 !important;width:100%;height:100%;display:table;z-index:0;">');
|
||||
myPanel.layout().addItem($frameArea);
|
||||
that.panel = myPanel;
|
||||
var frame = new wcIFrame($frameArea, myPanel);
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
||||
|
@ -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(
|
||||
|
@ -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])
|
||||
|
@ -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(
|
||||
|
@ -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(
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -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_css_selector(
|
||||
QueryToolLocatorsCss.btn_auto_commit).click()
|
||||
# close option
|
||||
query_op.click()
|
||||
|
||||
self.page.find_by_id("btn-auto-commit").click()
|
||||
|
||||
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_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()
|
||||
|
||||
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_check = auto_rollback_btn.find_element_by_tag_name("i")
|
||||
|
||||
# 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()
|
||||
|
||||
# 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):
|
||||
|
@ -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[]"]
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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 '<img src=\"x\" onerror=\"console.log(1)\">'"
|
||||
)
|
||||
@ -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')
|
||||
|
@ -54,14 +54,7 @@ define('pgadmin.datagrid', [
|
||||
self.preferences = pgBrowser.get_preferences_for_module('sqleditor');
|
||||
});
|
||||
|
||||
this.spinner_el =
|
||||
`<div class="pg-sp-container">
|
||||
<div class="pg-sp-content">
|
||||
<div class="row">
|
||||
<div class="col-12 pg-sp-icon"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>`;
|
||||
|
||||
// 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 =
|
||||
$(`<div class="pg-sp-container">
|
||||
<div class="pg-sp-content">
|
||||
<div class="row">
|
||||
<div class="col-12 pg-sp-icon"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>`).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);
|
||||
};
|
||||
|
@ -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:
|
||||
|
@ -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:
|
||||
|
@ -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_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()
|
||||
|
||||
def toggle_open_tree_item(self, tree_item_text):
|
||||
item = self.find_by_xpath(
|
||||
"//*[@id='tree']//*[.='" + tree_item_text +
|
||||
"']/../*[@class='aciTreeButton']")
|
||||
# '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)
|
||||
item.click()
|
||||
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
|
||||
|
||||
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 = WebDriverWait(
|
||||
self.driver, timeout=self.timeout, poll_frequency=0.01)\
|
||||
.until(find_codemirror,
|
||||
"Timed out waiting for codemirror to appear")
|
||||
|
||||
action = ActionChains(self.driver)
|
||||
action.send_keys(field_content)
|
||||
action.perform()
|
||||
time.sleep(1)
|
||||
codemirror_ele.click()
|
||||
|
||||
# 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)
|
||||
|
@ -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
|
||||
|
@ -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'
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user