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:
Usman Muzaffar 2019-03-21 12:04:37 +00:00 committed by Dave Page
parent 3f22503ad2
commit be26fc540c
20 changed files with 498 additions and 222 deletions

View File

@ -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);

View File

@ -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

View File

@ -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)

View File

@ -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(

View File

@ -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])

View File

@ -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(

View File

@ -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(

View File

@ -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)

View File

@ -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)

View File

@ -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):

View File

@ -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[]"]
}

View File

@ -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

View File

@ -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')

View File

@ -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);
};

View File

@ -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:

View File

@ -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:

View File

@ -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)

View File

@ -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

View File

@ -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'

View File

@ -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