Additional feature test fixes:

1) Changes required for working with Bootstrap 4.
2) Change to fix the timeout exception when waiting for element (tested multiple times on multiple server, did not occur to me thereafter)
3) Removed reset layout after each test case. Instead, delete the layout entry from sqlite db file and do a plain refresh. This will save some time and will also remove dependency on reset layout menu.
4) Disables tree state saving when feature test run starts. Feature tests got confused with auto expanding tree.
This commit is contained in:
Aditya Toshniwal
2018-10-17 11:50:22 +01:00
committed by Dave Page
parent ef0e53e8fc
commit 6fa6939f52
9 changed files with 85 additions and 25 deletions

View File

@@ -80,6 +80,7 @@ class BrowserToolBarFeatureTest(BaseFeatureTest):
self.page.find_by_xpath("//*[contains(@class,'wcTabIcon fa fa-bolt')]") self.page.find_by_xpath("//*[contains(@class,'wcTabIcon fa fa-bolt')]")
def test_view_data_tool_button(self): def test_view_data_tool_button(self):
self.page.select_tree_item(self.test_db)
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_tree_item('Tables')

View File

@@ -41,7 +41,7 @@ class CheckFileManagerFeatureTest(BaseFeatureTest):
os.remove(self.XSS_FILE) os.remove(self.XSS_FILE)
def after(self): def after(self):
self.page.close_query_tool('sql', False) self.page.close_query_tool('.sql', False)
self.page.remove_server(self.server) self.page.remove_server(self.server)
def runTest(self): def runTest(self):
@@ -179,3 +179,5 @@ class CheckFileManagerFeatureTest(BaseFeatureTest):
if not success: if not success:
raise Exception("Unable to sort in descending order while clicked " raise Exception("Unable to sort in descending order while clicked "
"on 'Name' column") "on 'Name' column")
self.page.click_modal('Cancel')

View File

@@ -74,11 +74,11 @@ class KeyboardShortcutFeatureTest(BaseFeatureTest):
EC.presence_of_element_located( EC.presence_of_element_located(
(By.XPATH, "//li[contains(@id, " + (By.XPATH, "//li[contains(@id, " +
s + s +
") and contains(@class, 'open')]") ") and contains(@class, 'show')]")
) )
) )
is_open = 'open' in self.page.find_by_id(s).get_attribute('class') is_open = 'show' in self.page.find_by_id(s).get_attribute('class')
assert is_open is True, "Keyboard shortcut change is unsuccessful." assert is_open is True, "Keyboard shortcut change is unsuccessful."

View File

@@ -29,6 +29,8 @@ try:
test_data_configuration['datatype_minimum_version'] test_data_configuration['datatype_minimum_version']
except Exception as e: except Exception as e:
print(str(e)) print(str(e))
assert False, \
"datatype_test.json file load failed"
class PGDataypeFeatureTest(BaseFeatureTest): class PGDataypeFeatureTest(BaseFeatureTest):
@@ -88,7 +90,7 @@ class PGDataypeFeatureTest(BaseFeatureTest):
".ajs-dialog.pg-el-container .ajs-maximize").click() ".ajs-dialog.pg-el-container .ajs-maximize").click()
sql_editor = self.page.find_by_xpath( sql_editor = self.page.find_by_xpath(
"//*[contains(@class,'aciTreeLi') and contains(.,'SQL Editor')]") "//*[contains(@class,'aciTreeLi') and contains(.,'Query Tool')]")
sql_editor.find_element_by_xpath( sql_editor.find_element_by_xpath(
"//*[contains(@class,'aciTreeText') and contains(.,'Options')]" "//*[contains(@class,'aciTreeText') and contains(.,'Options')]"

View File

@@ -55,10 +55,10 @@ class PGUtilitiesBackupFeatureTest(BaseFeatureTest):
self.page.find_by_partial_link_text("Backup...").click() self.page.find_by_partial_link_text("Backup...").click()
self.wait.until(EC.element_to_be_clickable( self.wait.until(EC.element_to_be_clickable(
(By.CSS_SELECTOR, ".browse_file_input"))) (By.CSS_SELECTOR, ".file [name='file']")))
self.wait.until(EC.element_to_be_clickable( self.wait.until(EC.element_to_be_clickable(
(By.CSS_SELECTOR, ".browse_file_input"))).click() (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")
@@ -98,15 +98,10 @@ class PGUtilitiesBackupFeatureTest(BaseFeatureTest):
self.page.find_by_partial_link_text("Restore...").click() self.page.find_by_partial_link_text("Restore...").click()
self.wait.until(EC.element_to_be_clickable( self.wait.until(EC.element_to_be_clickable(
(By.CSS_SELECTOR, ".browse_file_input"))) (By.CSS_SELECTOR, ".file [name='file']")))
self.page.find_by_xpath(
"//button[contains(@class,'fa-info') and "
"contains(@label, 'Restore')]"
)
self.wait.until(EC.element_to_be_clickable( self.wait.until(EC.element_to_be_clickable(
(By.CSS_SELECTOR, ".browse_file_input"))).click() (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")

View File

@@ -18,6 +18,7 @@ from copy import deepcopy
import config as app_config import config as app_config
from pgadmin.utils.route import BaseTestGenerator from pgadmin.utils.route import BaseTestGenerator
from regression.feature_utils.pgadmin_page import PgadminPage from regression.feature_utils.pgadmin_page import PgadminPage
from regression.python_test_utils import test_utils
class BaseFeatureTest(BaseTestGenerator): class BaseFeatureTest(BaseTestGenerator):
@@ -35,10 +36,11 @@ class BaseFeatureTest(BaseTestGenerator):
self.page = PgadminPage(self.driver, app_config) self.page = PgadminPage(self.driver, app_config)
try: try:
test_utils.reset_layout_db()
self.page.driver.switch_to.default_content() self.page.driver.switch_to.default_content()
self.page.wait_for_app() self.page.wait_for_app()
self.page.wait_for_spinner_to_disappear() self.page.wait_for_spinner_to_disappear()
self.page.reset_layout() self.page.refresh_page()
self.page.wait_for_spinner_to_disappear() self.page.wait_for_spinner_to_disappear()
self.before() self.before()
except Exception: except Exception:

View File

@@ -48,6 +48,9 @@ class PgadminPage:
self.click_modal('OK') self.click_modal('OK')
self.wait_for_reloading_indicator_to_disappear() self.wait_for_reloading_indicator_to_disappear()
def refresh_page(self):
self.driver.refresh()
def click_modal(self, button_text): def click_modal(self, button_text):
time.sleep(0.5) time.sleep(0.5)
# Find active alertify dialog in case of multiple alertify dialog # Find active alertify dialog in case of multiple alertify dialog
@@ -85,8 +88,7 @@ class PgadminPage:
self.driver.find_element_by_link_text("Tools").click() self.driver.find_element_by_link_text("Tools").click()
tools_menu = self.driver.find_element_by_id('mnu_tools') tools_menu = self.driver.find_element_by_id('mnu_tools')
# Query Tool is first li query_tool = tools_menu.find_element_by_id('query_tool')
query_tool = tools_menu.find_element_by_tag_name('li')
self.enable_menu_item(query_tool, 10) self.enable_menu_item(query_tool, 10)
@@ -98,11 +100,11 @@ class PgadminPage:
# wait until menu becomes enabled. # wait until menu becomes enabled.
while time.time() - start_time < wait_time: # wait_time seconds while time.time() - start_time < wait_time: # wait_time seconds
# if menu is disabled then it will have # if menu is disabled then it will have
# two classes 'menu-item disabled'. # two classes 'dropdown-item disabled'.
# And if menu is enabled the it will have # And if menu is enabled the it will have
# only one class 'menu-item'. # only one class 'dropdown-item'.
if 'menu-item' == str(menu_item.get_attribute('class')): if 'dropdown-item' == str(menu_item.get_attribute('class')):
break break
time.sleep(0.1) time.sleep(0.1)
else: else:
@@ -136,6 +138,8 @@ class PgadminPage:
server_to_remove = self.find_by_xpath( server_to_remove = self.find_by_xpath(
"//*[@id='tree']//*[.='" + server_config['name'] + "//*[@id='tree']//*[.='" + server_config['name'] +
"' and @class='aciTreeItem']") "' and @class='aciTreeItem']")
self.driver.execute_script(
"arguments[0].scrollIntoView()", server_to_remove)
self.click_element(server_to_remove) self.click_element(server_to_remove)
object_menu_item = self.find_by_partial_link_text("Object") object_menu_item = self.find_by_partial_link_text("Object")
self.click_element(object_menu_item) self.click_element(object_menu_item)
@@ -144,14 +148,19 @@ class PgadminPage:
self.click_modal('OK') self.click_modal('OK')
def select_tree_item(self, tree_item_text): def select_tree_item(self, tree_item_text):
self.find_by_xpath( item = self.find_by_xpath(
"//*[@id='tree']//*[.='" + tree_item_text + "//*[@id='tree']//*[.='" + tree_item_text +
"' and @class='aciTreeItem']").click() "' and @class='aciTreeItem']")
self.driver.execute_script("arguments[0].scrollIntoView()", item)
item.click()
def toggle_open_tree_item(self, tree_item_text): def toggle_open_tree_item(self, tree_item_text):
self.find_by_xpath( item = self.find_by_xpath(
"//*[@id='tree']//*[.='" + tree_item_text + "//*[@id='tree']//*[.='" + tree_item_text +
"']/../*[@class='aciTreeButton']").click() "']/../*[@class='aciTreeButton']")
self.driver.execute_script("arguments[0].scrollIntoView()", item)
item.click()
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):
@@ -276,11 +285,12 @@ class PgadminPage:
try: try:
element = find_method_with_args(driver) element = find_method_with_args(driver)
if element.is_displayed() and element.is_enabled(): if element.is_displayed() and element.is_enabled():
return element return True
except NoSuchElementException: except NoSuchElementException:
return False return False
return self._wait_for("element to exist", element_if_it_exists) self._wait_for("element to exist", element_if_it_exists)
return find_method_with_args(self.driver)
def wait_for_element_to_disappear(self, find_method_with_args): def wait_for_element_to_disappear(self, find_method_with_args):
def element_if_it_disappears(driver): def element_if_it_disappears(driver):

View File

@@ -435,6 +435,7 @@ def create_server(server):
' comment) VALUES (?,?,?,?,?,?,?,?,?,?)', server_details) ' comment) VALUES (?,?,?,?,?,?,?,?,?,?)', server_details)
server_id = cur.lastrowid server_id = cur.lastrowid
conn.commit() conn.commit()
conn.close()
# Add server info to parent_node_dict # Add server info to parent_node_dict
regression.parent_node_dict["server"].append( regression.parent_node_dict["server"].append(
{ {
@@ -639,6 +640,50 @@ def set_preference(default_binary_path):
) )
conn.commit() conn.commit()
conn.close()
def disable_tree_state_save():
conn = sqlite3.connect(config.TEST_SQLITE_PATH)
cur = conn.cursor()
pref = Preferences.module('browser')\
.preference('browser_tree_state_save_interval')
user_pref = cur.execute(
'SELECT pid, uid FROM user_preferences '
'where pid=?', (pref.pid,)
)
if len(user_pref.fetchall()) == 0:
cur.execute(
'INSERT INTO user_preferences(pid, uid, value)'
' VALUES (?,?,?)', (pref.pid, 1, -1)
)
else:
cur.execute(
'UPDATE user_preferences'
' SET VALUE = ?'
' WHERE PID = ?', (-1, pref.pid)
)
conn.commit()
conn.close()
def reset_layout_db(user_id=None):
conn = sqlite3.connect(config.TEST_SQLITE_PATH)
cur = conn.cursor()
if user_id is None:
cur.execute(
'DELETE FROM SETTING WHERE SETTING="Browser/Layout"'
)
else:
cur.execute(
'DELETE FROM SETTING WHERE SETTING="Browser/Layout"'
' AND USER_ID=?', user_id
)
conn.commit()
conn.close()
def remove_db_file(): def remove_db_file():

View File

@@ -419,6 +419,9 @@ if __name__ == '__main__':
if server['default_binary_paths'] is not None: if server['default_binary_paths'] is not None:
test_utils.set_preference(server['default_binary_paths']) test_utils.set_preference(server['default_binary_paths'])
# Disable tree state saving
test_utils.disable_tree_state_save()
suite = get_suite(test_module_list, suite = get_suite(test_module_list,
server, server,
test_client, test_client,