mirror of
https://github.com/pgadmin-org/pgadmin4.git
synced 2025-02-25 18:55:31 -06:00
Feature test stabilisation.
This commit is contained in:
parent
ee37be56f9
commit
dcd163ac02
@ -67,9 +67,9 @@ class CheckFileManagerFeatureTest(BaseFeatureTest):
|
|||||||
def _create_new_file(self):
|
def _create_new_file(self):
|
||||||
self.page.find_by_css_selector(QueryToolLocatorsCss.btn_save).click()
|
self.page.find_by_css_selector(QueryToolLocatorsCss.btn_save).click()
|
||||||
# Set the XSS value in input
|
# Set the XSS value in input
|
||||||
print('Create file')
|
|
||||||
self.page.find_by_css_selector('.change_file_types')
|
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
|
# Save the file
|
||||||
self.page.click_modal('Create')
|
self.page.click_modal('Create')
|
||||||
self.page.wait_for_query_tool_loading_indicator_to_disappear()
|
self.page.wait_for_query_tool_loading_indicator_to_disappear()
|
||||||
|
@ -53,6 +53,8 @@ class PGUtilitiesBackupFeatureTest(BaseFeatureTest):
|
|||||||
|
|
||||||
self.wait = WebDriverWait(self.page.driver, 20)
|
self.wait = WebDriverWait(self.page.driver, 20)
|
||||||
|
|
||||||
|
test_gui_helper.close_bgprocess_popup(self)
|
||||||
|
|
||||||
def runTest(self):
|
def runTest(self):
|
||||||
self.page.toggle_open_server(self.server['name'])
|
self.page.toggle_open_server(self.server['name'])
|
||||||
self.page.toggle_open_tree_item('Databases')
|
self.page.toggle_open_tree_item('Databases')
|
||||||
@ -68,7 +70,6 @@ class PGUtilitiesBackupFeatureTest(BaseFeatureTest):
|
|||||||
|
|
||||||
self.wait.until(EC.element_to_be_clickable(
|
self.wait.until(EC.element_to_be_clickable(
|
||||||
(By.CSS_SELECTOR, ".file [name='file']"))).click()
|
(By.CSS_SELECTOR, ".file [name='file']"))).click()
|
||||||
# .input-group-append >button
|
|
||||||
self.page.fill_input_by_field_name(
|
self.page.fill_input_by_field_name(
|
||||||
"file", "test_backup", loose_focus=True)
|
"file", "test_backup", loose_focus=True)
|
||||||
|
|
||||||
@ -77,11 +78,10 @@ class PGUtilitiesBackupFeatureTest(BaseFeatureTest):
|
|||||||
|
|
||||||
self.page.find_by_css_selector('.ajs-bg-bgprocess')
|
self.page.find_by_css_selector('.ajs-bg-bgprocess')
|
||||||
|
|
||||||
# status = self.page.find_by_css_selector(
|
status = test_utils.get_watcher_dialogue_status(self)
|
||||||
# ".pg-bg-status .bg-success-light .pg-bg-status-text").text
|
|
||||||
|
|
||||||
status = self.page.find_by_css_selector(
|
if status != "Successfully completed.":
|
||||||
".pg-bg-status-text").text
|
test_gui_helper.close_bgprocess_popup(self)
|
||||||
|
|
||||||
self.assertEquals(status, "Successfully completed.")
|
self.assertEquals(status, "Successfully completed.")
|
||||||
|
|
||||||
@ -130,8 +130,11 @@ class PGUtilitiesBackupFeatureTest(BaseFeatureTest):
|
|||||||
|
|
||||||
self.page.find_by_css_selector('.ajs-bg-bgprocess')
|
self.page.find_by_css_selector('.ajs-bg-bgprocess')
|
||||||
|
|
||||||
status = self.page.find_by_css_selector(
|
status = test_utils.get_watcher_dialogue_status(self)
|
||||||
".pg-bg-status-text").text
|
|
||||||
|
if status != "Successfully completed.":
|
||||||
|
test_gui_helper.close_bgprocess_popup(self)
|
||||||
|
|
||||||
self.assertEquals(status, "Successfully completed.")
|
self.assertEquals(status, "Successfully completed.")
|
||||||
|
|
||||||
self.page.find_by_css_selector(
|
self.page.find_by_css_selector(
|
||||||
@ -158,7 +161,6 @@ class PGUtilitiesBackupFeatureTest(BaseFeatureTest):
|
|||||||
os.remove(backup_file)
|
os.remove(backup_file)
|
||||||
|
|
||||||
def after(self):
|
def after(self):
|
||||||
test_gui_helper.close_bgprocess_popup(self)
|
|
||||||
self.page.remove_server(self.server)
|
self.page.remove_server(self.server)
|
||||||
connection = test_utils.get_db_connection(
|
connection = test_utils.get_db_connection(
|
||||||
self.server['db'],
|
self.server['db'],
|
||||||
|
@ -61,6 +61,7 @@ class PGUtilitiesMaintenanceFeatureTest(BaseFeatureTest):
|
|||||||
self.table_name)
|
self.table_name)
|
||||||
self.page.add_server(self.server)
|
self.page.add_server(self.server)
|
||||||
self.wait = WebDriverWait(self.page.driver, 20)
|
self.wait = WebDriverWait(self.page.driver, 20)
|
||||||
|
test_gui_helper.close_bgprocess_popup(self)
|
||||||
|
|
||||||
def runTest(self):
|
def runTest(self):
|
||||||
self._open_maintenance_dialogue()
|
self._open_maintenance_dialogue()
|
||||||
@ -75,7 +76,7 @@ class PGUtilitiesMaintenanceFeatureTest(BaseFeatureTest):
|
|||||||
if self.test_level == 'table':
|
if self.test_level == 'table':
|
||||||
self.page.toggle_open_tree_item('Schemas')
|
self.page.toggle_open_tree_item('Schemas')
|
||||||
self.page.toggle_open_tree_item('public')
|
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.page.select_tree_item(self.table_name)
|
||||||
|
|
||||||
self.driver.find_element_by_link_text("Tools").click()
|
self.driver.find_element_by_link_text("Tools").click()
|
||||||
@ -83,8 +84,10 @@ class PGUtilitiesMaintenanceFeatureTest(BaseFeatureTest):
|
|||||||
time.sleep(0.5)
|
time.sleep(0.5)
|
||||||
|
|
||||||
def _verify_command(self):
|
def _verify_command(self):
|
||||||
status = self.page.find_by_css_selector(
|
status = test_utils.get_watcher_dialogue_status(self)
|
||||||
".pg-bg-status-text").text
|
if status != "Successfully completed.":
|
||||||
|
test_gui_helper.close_bgprocess_popup(self)
|
||||||
|
|
||||||
self.assertEquals(status, "Successfully completed.")
|
self.assertEquals(status, "Successfully completed.")
|
||||||
self.page.find_by_css_selector(".pg-bg-more-details").click()
|
self.page.find_by_css_selector(".pg-bg-more-details").click()
|
||||||
command = self.page.find_by_css_selector(
|
command = self.page.find_by_css_selector(
|
||||||
@ -113,7 +116,6 @@ class PGUtilitiesMaintenanceFeatureTest(BaseFeatureTest):
|
|||||||
"div.wcFloatingFocus div.fa-close").click()
|
"div.wcFloatingFocus div.fa-close").click()
|
||||||
|
|
||||||
def after(self):
|
def after(self):
|
||||||
test_gui_helper.close_bgprocess_popup(self)
|
|
||||||
self.page.remove_server(self.server)
|
self.page.remove_server(self.server)
|
||||||
connection = test_utils.get_db_connection(
|
connection = test_utils.get_db_connection(
|
||||||
self.server['db'],
|
self.server['db'],
|
||||||
|
@ -36,6 +36,10 @@ class CheckDebuggerForXssFeatureTest(BaseFeatureTest):
|
|||||||
self.server, "postgres", "a_test_function"
|
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):
|
def runTest(self):
|
||||||
self.page.wait_for_spinner_to_disappear()
|
self.page.wait_for_spinner_to_disappear()
|
||||||
self.page.add_server(self.server)
|
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('postgres')
|
||||||
self.page.toggle_open_tree_item('Schemas')
|
self.page.toggle_open_tree_item('Schemas')
|
||||||
self.page.toggle_open_tree_item('public')
|
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()")
|
self.page.select_tree_item("a_test_function()")
|
||||||
|
|
||||||
def _debug_function(self):
|
def _debug_function(self):
|
||||||
|
@ -58,7 +58,8 @@ class CheckRoleMembershipControlFeatureTest(BaseFeatureTest):
|
|||||||
def _check_role_membership_control(self):
|
def _check_role_membership_control(self):
|
||||||
self.page.driver.find_element_by_link_text("Object").click()
|
self.page.driver.find_element_by_link_text("Object").click()
|
||||||
self.page.driver.find_element_by_link_text("Properties...").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
|
# Fetch the source code for our custom control
|
||||||
source_code = self.page.find_by_xpath(
|
source_code = self.page.find_by_xpath(
|
||||||
"//div[contains(@class,'rolmembership')]"
|
"//div[contains(@class,'rolmembership')]"
|
||||||
@ -78,3 +79,19 @@ class CheckRoleMembershipControlFeatureTest(BaseFeatureTest):
|
|||||||
# For XSS we need to search against element's html code
|
# For XSS we need to search against element's html code
|
||||||
assert source_code.find(string_to_find) != - \
|
assert source_code.find(string_to_find) != - \
|
||||||
1, "{0} might be vulnerable to XSS ".format(source)
|
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
|
import time
|
||||||
|
|
||||||
|
from selenium import webdriver
|
||||||
from selenium.common.exceptions import NoSuchElementException, \
|
from selenium.common.exceptions import NoSuchElementException, \
|
||||||
WebDriverException, TimeoutException, NoSuchWindowException, \
|
WebDriverException, TimeoutException, NoSuchWindowException, \
|
||||||
StaleElementReferenceException
|
StaleElementReferenceException
|
||||||
@ -71,7 +72,8 @@ class PgadminPage:
|
|||||||
.perform()
|
.perform()
|
||||||
self.find_by_partial_link_text("Server...").click()
|
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.find_by_partial_link_text("Connection").click()
|
||||||
self.fill_input_by_field_name("host", server_config['host'])
|
self.fill_input_by_field_name("host", server_config['host'])
|
||||||
self.fill_input_by_field_name("port", server_config['port'])
|
self.fill_input_by_field_name("port", server_config['port'])
|
||||||
@ -151,7 +153,18 @@ class PgadminPage:
|
|||||||
"//*[@id='tree']//*[contains(text(), '" + tree_item_text + "')]"
|
"//*[@id='tree']//*[contains(text(), '" + tree_item_text + "')]"
|
||||||
"/parent::span[@class='aciTreeItem']")
|
"/parent::span[@class='aciTreeItem']")
|
||||||
self.driver.execute_script("arguments[0].scrollIntoView()", item)
|
self.driver.execute_script("arguments[0].scrollIntoView()", item)
|
||||||
item.click()
|
# 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):
|
def toggle_open_servers_group(self):
|
||||||
"""This will open Servers group to display underlying nodes"""
|
"""This will open Servers group to display underlying nodes"""
|
||||||
@ -197,13 +210,66 @@ class PgadminPage:
|
|||||||
"='Tables']]]/span[@class='aciTreeButton']")
|
"='Tables']]]/span[@class='aciTreeButton']")
|
||||||
ActionChains(self.driver).click(item_button).perform()
|
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 toggle_open_server(self, tree_item_text):
|
||||||
def check_for_password_dialog_or_tree_open(driver):
|
def check_for_password_dialog_or_tree_open(driver):
|
||||||
try:
|
try:
|
||||||
dialog = driver.find_element_by_id("frmPassword")
|
dialog = driver.find_element_by_id("frmPassword")
|
||||||
except WebDriverException:
|
except WebDriverException:
|
||||||
dialog = None
|
dialog = None
|
||||||
|
|
||||||
try:
|
try:
|
||||||
database_node = driver.find_element_by_xpath(
|
database_node = driver.find_element_by_xpath(
|
||||||
"//*[@id='tree']//*[.='Databases']"
|
"//*[@id='tree']//*[.='Databases']"
|
||||||
@ -284,8 +350,15 @@ class PgadminPage:
|
|||||||
|
|
||||||
def fill_input(self, field, field_content, input_keys=False,
|
def fill_input(self, field, field_content, input_keys=False,
|
||||||
key_after_input=Keys.ARROW_DOWN):
|
key_after_input=Keys.ARROW_DOWN):
|
||||||
field.click()
|
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
|
# Use send keys if input_keys true, else use javascript to set content
|
||||||
if input_keys:
|
if input_keys:
|
||||||
backspaces = [Keys.BACKSPACE] * len(field.get_attribute('value'))
|
backspaces = [Keys.BACKSPACE] * len(field.get_attribute('value'))
|
||||||
|
@ -10,14 +10,15 @@
|
|||||||
|
|
||||||
def close_bgprocess_popup(tester):
|
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)
|
# In cases where backup div is not closed (sometime due to some error)
|
||||||
try:
|
try:
|
||||||
if tester.driver.find_element_by_css_selector(
|
if tester.driver.find_element_by_css_selector(
|
||||||
".ajs-message.ajs-bg-bgprocess.ajs-visible"):
|
".ajs-message.ajs-bg-bgprocess.ajs-visible"):
|
||||||
|
tester._screenshot()
|
||||||
|
screen_shot_taken = True
|
||||||
tester.driver.find_element_by_css_selector(
|
tester.driver.find_element_by_css_selector(
|
||||||
".btn.btn-sm-sq.btn-primary.pg-bg-close > i").click()
|
".btn.btn-sm-sq.btn-primary.pg-bg-close > i").click()
|
||||||
except Exception:
|
except Exception:
|
||||||
@ -28,6 +29,8 @@ def close_bgprocess_popup(tester):
|
|||||||
if tester.driver.find_element_by_xpath(
|
if tester.driver.find_element_by_xpath(
|
||||||
"//div[@class='card-header bg-primary d-flex']/div"
|
"//div[@class='card-header bg-primary d-flex']/div"
|
||||||
"[contains(text(), 'Restoring backup')]"):
|
"[contains(text(), 'Restoring backup')]"):
|
||||||
|
tester._screenshot()
|
||||||
|
screen_shot_taken = True
|
||||||
tester.driver.find_element_by_css_selector(
|
tester.driver.find_element_by_css_selector(
|
||||||
".btn.btn-sm-sq.btn-primary.pg-bg-close > i").click()
|
".btn.btn-sm-sq.btn-primary.pg-bg-close > i").click()
|
||||||
except Exception:
|
except Exception:
|
||||||
@ -39,7 +42,12 @@ def close_bgprocess_popup(tester):
|
|||||||
if tester.driver.find_element_by_xpath(
|
if tester.driver.find_element_by_xpath(
|
||||||
"//div[@class='card-header bg-primary d-flex']/div"
|
"//div[@class='card-header bg-primary d-flex']/div"
|
||||||
"[contains(text(), 'Maintenance')]"):
|
"[contains(text(), 'Maintenance')]"):
|
||||||
|
tester._screenshot()
|
||||||
|
screen_shot_taken = True
|
||||||
tester.driver.find_element_by_css_selector(
|
tester.driver.find_element_by_css_selector(
|
||||||
".btn.btn-sm-sq.btn-primary.pg-bg-close > i").click()
|
".btn.btn-sm-sq.btn-primary.pg-bg-close > i").click()
|
||||||
except Exception:
|
except Exception:
|
||||||
pass
|
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)
|
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"):
|
def create_role(server, db_name, role_name="test_role"):
|
||||||
try:
|
try:
|
||||||
connection = get_db_connection(
|
connection = get_db_connection(
|
||||||
@ -1006,3 +1026,22 @@ def check_binary_path_or_skip_test(cls, utility_name):
|
|||||||
retVal = is_utility_exists(binary_path)
|
retVal = is_utility_exists(binary_path)
|
||||||
if retVal is not None:
|
if retVal is not None:
|
||||||
cls.skipTest(retVal)
|
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
Block a user