Feature test stabilisation.
parent
ee37be56f9
commit
dcd163ac02
|
@ -67,9 +67,9 @@ class CheckFileManagerFeatureTest(BaseFeatureTest):
|
|||
def _create_new_file(self):
|
||||
self.page.find_by_css_selector(QueryToolLocatorsCss.btn_save).click()
|
||||
# Set the XSS value in input
|
||||
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)
|
||||
self.page.fill_input_by_css_selector("input#file-input-path",
|
||||
self.XSS_FILE)
|
||||
# Save the file
|
||||
self.page.click_modal('Create')
|
||||
self.page.wait_for_query_tool_loading_indicator_to_disappear()
|
||||
|
|
|
@ -53,6 +53,8 @@ class PGUtilitiesBackupFeatureTest(BaseFeatureTest):
|
|||
|
||||
self.wait = WebDriverWait(self.page.driver, 20)
|
||||
|
||||
test_gui_helper.close_bgprocess_popup(self)
|
||||
|
||||
def runTest(self):
|
||||
self.page.toggle_open_server(self.server['name'])
|
||||
self.page.toggle_open_tree_item('Databases')
|
||||
|
@ -68,7 +70,6 @@ class PGUtilitiesBackupFeatureTest(BaseFeatureTest):
|
|||
|
||||
self.wait.until(EC.element_to_be_clickable(
|
||||
(By.CSS_SELECTOR, ".file [name='file']"))).click()
|
||||
# .input-group-append >button
|
||||
self.page.fill_input_by_field_name(
|
||||
"file", "test_backup", loose_focus=True)
|
||||
|
||||
|
@ -77,11 +78,10 @@ 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
|
||||
status = test_utils.get_watcher_dialogue_status(self)
|
||||
|
||||
status = self.page.find_by_css_selector(
|
||||
".pg-bg-status-text").text
|
||||
if status != "Successfully completed.":
|
||||
test_gui_helper.close_bgprocess_popup(self)
|
||||
|
||||
self.assertEquals(status, "Successfully completed.")
|
||||
|
||||
|
@ -130,8 +130,11 @@ class PGUtilitiesBackupFeatureTest(BaseFeatureTest):
|
|||
|
||||
self.page.find_by_css_selector('.ajs-bg-bgprocess')
|
||||
|
||||
status = self.page.find_by_css_selector(
|
||||
".pg-bg-status-text").text
|
||||
status = test_utils.get_watcher_dialogue_status(self)
|
||||
|
||||
if status != "Successfully completed.":
|
||||
test_gui_helper.close_bgprocess_popup(self)
|
||||
|
||||
self.assertEquals(status, "Successfully completed.")
|
||||
|
||||
self.page.find_by_css_selector(
|
||||
|
@ -158,7 +161,6 @@ class PGUtilitiesBackupFeatureTest(BaseFeatureTest):
|
|||
os.remove(backup_file)
|
||||
|
||||
def after(self):
|
||||
test_gui_helper.close_bgprocess_popup(self)
|
||||
self.page.remove_server(self.server)
|
||||
connection = test_utils.get_db_connection(
|
||||
self.server['db'],
|
||||
|
|
|
@ -61,6 +61,7 @@ class PGUtilitiesMaintenanceFeatureTest(BaseFeatureTest):
|
|||
self.table_name)
|
||||
self.page.add_server(self.server)
|
||||
self.wait = WebDriverWait(self.page.driver, 20)
|
||||
test_gui_helper.close_bgprocess_popup(self)
|
||||
|
||||
def runTest(self):
|
||||
self._open_maintenance_dialogue()
|
||||
|
@ -75,7 +76,7 @@ class PGUtilitiesMaintenanceFeatureTest(BaseFeatureTest):
|
|||
if self.test_level == 'table':
|
||||
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.table_name)
|
||||
|
||||
self.driver.find_element_by_link_text("Tools").click()
|
||||
|
@ -83,8 +84,10 @@ class PGUtilitiesMaintenanceFeatureTest(BaseFeatureTest):
|
|||
time.sleep(0.5)
|
||||
|
||||
def _verify_command(self):
|
||||
status = self.page.find_by_css_selector(
|
||||
".pg-bg-status-text").text
|
||||
status = test_utils.get_watcher_dialogue_status(self)
|
||||
if status != "Successfully completed.":
|
||||
test_gui_helper.close_bgprocess_popup(self)
|
||||
|
||||
self.assertEquals(status, "Successfully completed.")
|
||||
self.page.find_by_css_selector(".pg-bg-more-details").click()
|
||||
command = self.page.find_by_css_selector(
|
||||
|
@ -113,7 +116,6 @@ class PGUtilitiesMaintenanceFeatureTest(BaseFeatureTest):
|
|||
"div.wcFloatingFocus div.fa-close").click()
|
||||
|
||||
def after(self):
|
||||
test_gui_helper.close_bgprocess_popup(self)
|
||||
self.page.remove_server(self.server)
|
||||
connection = test_utils.get_db_connection(
|
||||
self.server['db'],
|
||||
|
|
|
@ -36,6 +36,10 @@ class CheckDebuggerForXssFeatureTest(BaseFeatureTest):
|
|||
self.server, "postgres", "a_test_function"
|
||||
)
|
||||
|
||||
if test_utils.does_function_exist(self.server, 'postgres',
|
||||
'a_test_function') != 'True':
|
||||
raise Exception("The required function is not found")
|
||||
|
||||
def runTest(self):
|
||||
self.page.wait_for_spinner_to_disappear()
|
||||
self.page.add_server(self.server)
|
||||
|
@ -53,7 +57,7 @@ class CheckDebuggerForXssFeatureTest(BaseFeatureTest):
|
|||
self.page.toggle_open_tree_item('postgres')
|
||||
self.page.toggle_open_tree_item('Schemas')
|
||||
self.page.toggle_open_tree_item('public')
|
||||
self.page.toggle_open_tree_item('Functions')
|
||||
self.page.toggle_open_function_node()
|
||||
self.page.select_tree_item("a_test_function()")
|
||||
|
||||
def _debug_function(self):
|
||||
|
|
|
@ -58,7 +58,8 @@ class CheckRoleMembershipControlFeatureTest(BaseFeatureTest):
|
|||
def _check_role_membership_control(self):
|
||||
self.page.driver.find_element_by_link_text("Object").click()
|
||||
self.page.driver.find_element_by_link_text("Properties...").click()
|
||||
self.page.find_by_partial_link_text("Membership").click()
|
||||
# self.page.find_by_partial_link_text("Membership").click()
|
||||
self.click_membership_tab()
|
||||
# Fetch the source code for our custom control
|
||||
source_code = self.page.find_by_xpath(
|
||||
"//div[contains(@class,'rolmembership')]"
|
||||
|
@ -78,3 +79,19 @@ class CheckRoleMembershipControlFeatureTest(BaseFeatureTest):
|
|||
# For XSS we need to search against element's html code
|
||||
assert source_code.find(string_to_find) != - \
|
||||
1, "{0} might be vulnerable to XSS ".format(source)
|
||||
|
||||
def click_membership_tab(self):
|
||||
"""This will click and open membership tab of role"""
|
||||
success = False
|
||||
attempts = 3
|
||||
while not success and attempts > 0:
|
||||
membership_tab_link = self.page.find_by_xpath(
|
||||
"//a[normalize-space(text())='Membership']")
|
||||
membership_tab_link.click()
|
||||
try:
|
||||
self.page.find_by_xpath("//input[@placeholder="
|
||||
"'Select members']")
|
||||
break
|
||||
except Exception as e:
|
||||
attempts -= 1
|
||||
pass
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
|
||||
import time
|
||||
|
||||
from selenium import webdriver
|
||||
from selenium.common.exceptions import NoSuchElementException, \
|
||||
WebDriverException, TimeoutException, NoSuchWindowException, \
|
||||
StaleElementReferenceException
|
||||
|
@ -71,7 +72,8 @@ class PgadminPage:
|
|||
.perform()
|
||||
self.find_by_partial_link_text("Server...").click()
|
||||
|
||||
self.fill_input_by_field_name("name", server_config['name'])
|
||||
self.fill_input_by_field_name("name", server_config['name'],
|
||||
loose_focus=True)
|
||||
self.find_by_partial_link_text("Connection").click()
|
||||
self.fill_input_by_field_name("host", server_config['host'])
|
||||
self.fill_input_by_field_name("port", server_config['port'])
|
||||
|
@ -151,7 +153,18 @@ class PgadminPage:
|
|||
"//*[@id='tree']//*[contains(text(), '" + tree_item_text + "')]"
|
||||
"/parent::span[@class='aciTreeItem']")
|
||||
self.driver.execute_script("arguments[0].scrollIntoView()", item)
|
||||
# unexpected exception like element overlapping, click attempts more
|
||||
# than one time
|
||||
attempts = 3
|
||||
while attempts > 0:
|
||||
try:
|
||||
item.click()
|
||||
break
|
||||
except Exception as e:
|
||||
attempts -= 1
|
||||
time.sleep(.4)
|
||||
if attempts == 0:
|
||||
raise Exception(e)
|
||||
|
||||
def toggle_open_servers_group(self):
|
||||
"""This will open Servers group to display underlying nodes"""
|
||||
|
@ -197,13 +210,66 @@ class PgadminPage:
|
|||
"='Tables']]]/span[@class='aciTreeButton']")
|
||||
ActionChains(self.driver).click(item_button).perform()
|
||||
|
||||
def toggle_open_function_node(self):
|
||||
"""The function will be used for opening Functions node only"""
|
||||
node_expanded = False
|
||||
attempts = 3
|
||||
|
||||
xpath_for_functions_node = \
|
||||
"//span[@class='aciTreeText' and starts-with(text()," \
|
||||
"'Functions')]"
|
||||
xpath_for_exp = "//div[div[div[div[div[div[div[div[span[span[" \
|
||||
"(@class='aciTreeText') and starts-with(text()," \
|
||||
"'Functions')]]]]]]]]]]"
|
||||
xpath_for_button = "//div[span[span[(@class='aciTreeText') " \
|
||||
"and starts-with(text(),'Functions')]]]" \
|
||||
"/span[@class='aciTreeButton']"
|
||||
|
||||
while node_expanded is not True and attempts > 0:
|
||||
# get the element which contains 'aria-expanded' info
|
||||
|
||||
xpath_for_refresh_btn = "//li[@class='context-menu-item']" \
|
||||
"/span[text()='Refresh...']"
|
||||
|
||||
# add code to refresh button, sometime the the collapsing button
|
||||
# is not visible even if there is sub node.
|
||||
functions_node_ele = self.find_by_xpath(xpath_for_functions_node)
|
||||
|
||||
webdriver.ActionChains(self.driver).move_to_element(
|
||||
functions_node_ele).context_click().perform()
|
||||
refresh_btn = self.find_by_xpath(xpath_for_refresh_btn)
|
||||
refresh_btn.click()
|
||||
time.sleep(.5)
|
||||
|
||||
# get the expansion status
|
||||
function_expansion_ele = self.find_by_xpath(xpath_for_exp)
|
||||
|
||||
# look into the attribute and check if it is already expanded or
|
||||
# not
|
||||
if function_expansion_ele.get_attribute('aria-expanded') \
|
||||
== 'false':
|
||||
# button element of the Function node to open it
|
||||
item_button = self.find_by_xpath(xpath_for_button)
|
||||
ActionChains(self.driver).click(item_button).perform()
|
||||
# Expansion of element on GUI takes sometime, so put small
|
||||
# sleep
|
||||
time.sleep(.5)
|
||||
function_expansion_ele = self.find_by_xpath(
|
||||
xpath_for_exp)
|
||||
if function_expansion_ele.get_attribute('aria-expanded') \
|
||||
== 'true':
|
||||
break
|
||||
else:
|
||||
attempts -= 1
|
||||
else:
|
||||
node_expanded = True
|
||||
|
||||
def toggle_open_server(self, tree_item_text):
|
||||
def check_for_password_dialog_or_tree_open(driver):
|
||||
try:
|
||||
dialog = driver.find_element_by_id("frmPassword")
|
||||
except WebDriverException:
|
||||
dialog = None
|
||||
|
||||
try:
|
||||
database_node = driver.find_element_by_xpath(
|
||||
"//*[@id='tree']//*[.='Databases']"
|
||||
|
@ -284,8 +350,15 @@ class PgadminPage:
|
|||
|
||||
def fill_input(self, field, field_content, input_keys=False,
|
||||
key_after_input=Keys.ARROW_DOWN):
|
||||
try:
|
||||
attempt = 0
|
||||
for attempt in range(0, 3):
|
||||
field.click()
|
||||
|
||||
break
|
||||
except Exception as e:
|
||||
time.sleep(.2)
|
||||
if attempt == 2:
|
||||
raise Exception(e)
|
||||
# Use send keys if input_keys true, else use javascript to set content
|
||||
if input_keys:
|
||||
backspaces = [Keys.BACKSPACE] * len(field.get_attribute('value'))
|
||||
|
|
|
@ -10,14 +10,15 @@
|
|||
|
||||
def close_bgprocess_popup(tester):
|
||||
"""
|
||||
Allow us to close the background process popup window
|
||||
Allows us to close the background process popup window
|
||||
"""
|
||||
tester._screenshot()
|
||||
|
||||
screen_shot_taken = False
|
||||
# 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"):
|
||||
tester._screenshot()
|
||||
screen_shot_taken = True
|
||||
tester.driver.find_element_by_css_selector(
|
||||
".btn.btn-sm-sq.btn-primary.pg-bg-close > i").click()
|
||||
except Exception:
|
||||
|
@ -28,6 +29,8 @@ def close_bgprocess_popup(tester):
|
|||
if tester.driver.find_element_by_xpath(
|
||||
"//div[@class='card-header bg-primary d-flex']/div"
|
||||
"[contains(text(), 'Restoring backup')]"):
|
||||
tester._screenshot()
|
||||
screen_shot_taken = True
|
||||
tester.driver.find_element_by_css_selector(
|
||||
".btn.btn-sm-sq.btn-primary.pg-bg-close > i").click()
|
||||
except Exception:
|
||||
|
@ -39,7 +42,12 @@ def close_bgprocess_popup(tester):
|
|||
if tester.driver.find_element_by_xpath(
|
||||
"//div[@class='card-header bg-primary d-flex']/div"
|
||||
"[contains(text(), 'Maintenance')]"):
|
||||
tester._screenshot()
|
||||
screen_shot_taken = True
|
||||
tester.driver.find_element_by_css_selector(
|
||||
".btn.btn-sm-sq.btn-primary.pg-bg-close > i").click()
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
if not screen_shot_taken:
|
||||
tester._screenshot()
|
||||
|
|
|
@ -319,6 +319,26 @@ def drop_debug_function(server, db_name, function_name="test_func"):
|
|||
traceback.print_exc(file=sys.stderr)
|
||||
|
||||
|
||||
def does_function_exist(server, db_name, fun_name):
|
||||
query = "select exists(select * " \
|
||||
"from pg_proc where proname = '%s');" % fun_name
|
||||
|
||||
connection = get_db_connection(
|
||||
db_name,
|
||||
server['username'],
|
||||
server['db_password'],
|
||||
server['host'],
|
||||
server['port'],
|
||||
server['sslmode']
|
||||
)
|
||||
|
||||
cursor = connection.cursor()
|
||||
|
||||
cursor.execute(query)
|
||||
result = cursor.fetchall()
|
||||
return str(result[0][0])
|
||||
|
||||
|
||||
def create_role(server, db_name, role_name="test_role"):
|
||||
try:
|
||||
connection = get_db_connection(
|
||||
|
@ -1006,3 +1026,22 @@ def check_binary_path_or_skip_test(cls, utility_name):
|
|||
retVal = is_utility_exists(binary_path)
|
||||
if retVal is not None:
|
||||
cls.skipTest(retVal)
|
||||
|
||||
|
||||
def get_watcher_dialogue_status(self):
|
||||
"""This will get watcher dialogue status"""
|
||||
import time
|
||||
attempts = 120
|
||||
|
||||
while attempts > 0:
|
||||
status = self.page.find_by_css_selector(
|
||||
".pg-bg-status-text").text
|
||||
|
||||
if 'Failed' in status:
|
||||
break
|
||||
if status == 'Started' or status == 'Running...':
|
||||
attempts -= 1
|
||||
time.sleep(.5)
|
||||
else:
|
||||
break
|
||||
return status
|
||||
|
|
Loading…
Reference in New Issue