Fixed feature tests.

Changes included:
  1. Created function for traversing the browser tree.
  2. Fixed some synchronization issues.
  3. Modified locators.
  4. Test cases fix for the recent commits.
This commit is contained in:
Shubham Agarwal 2019-11-11 10:49:00 +05:30 committed by Akshay Joshi
parent ea0c077180
commit b48121335c
18 changed files with 590 additions and 155 deletions

View File

@ -47,7 +47,7 @@ class BrowserToolBarFeatureTest(BaseFeatureTest):
file=sys.stderr, end="") file=sys.stderr, end="")
self.test_view_data_tool_button() self.test_view_data_tool_button()
print("OK.", file=sys.stderr) print("OK.", file=sys.stderr)
#
# Check for filtered rows button # Check for filtered rows button
print("\nFiltered Rows ToolBar Button ", print("\nFiltered Rows ToolBar Button ",
file=sys.stderr, end="") file=sys.stderr, end="")
@ -60,9 +60,9 @@ class BrowserToolBarFeatureTest(BaseFeatureTest):
self.test_table_name) self.test_table_name)
def test_query_tool_button(self): def test_query_tool_button(self):
self.page.toggle_open_tree_item(self.server['name']) self.page.expand_database_node(
self.page.toggle_open_tree_item('Databases') self.server['name'],
self.page.toggle_open_tree_item(self.test_db) self.server['db_password'], self.test_db)
self.page.retry_click( self.page.retry_click(
(By.CSS_SELECTOR, (By.CSS_SELECTOR,
BrowserToolBarLocators.open_query_tool_button_css), BrowserToolBarLocators.open_query_tool_button_css),
@ -70,9 +70,12 @@ class BrowserToolBarFeatureTest(BaseFeatureTest):
def test_view_data_tool_button(self): def test_view_data_tool_button(self):
self.page.select_tree_item(self.test_db) self.page.select_tree_item(self.test_db)
self.page.toggle_open_tree_item('Schemas') self.page.toggle_open_schema_node(
self.page.toggle_open_tree_item('public') self.server['name'], self.server['db_password'],
self.page.toggle_open_tables_node() self.test_db, 'public')
self.page.toggle_open_tables_node(
self.server['name'], self.server['db_password'],
self.test_db, 'public')
self.page.select_tree_item(self.test_table_name) self.page.select_tree_item(self.test_table_name)
self.page.retry_click( self.page.retry_click(

View File

@ -39,9 +39,9 @@ class CopySelectedQueryResultsFeatureTest(BaseFeatureTest):
self.server, self.test_db, self.test_table_name) self.server, self.test_db, self.test_table_name)
def runTest(self): def runTest(self):
self.page.toggle_open_tree_item(self.server['name']) self.page.expand_database_node(
self.page.toggle_open_tree_item('Databases') self.server['name'],
self.page.toggle_open_tree_item(self.test_db) self.server['db_password'], self.test_db)
self.page.open_query_tool() self.page.open_query_tool()
self.page.fill_codemirror_area_with( self.page.fill_codemirror_area_with(
@ -70,7 +70,7 @@ class CopySelectedQueryResultsFeatureTest(BaseFeatureTest):
QueryToolLocators.copy_button_css) QueryToolLocators.copy_button_css)
copy_button.click() copy_button.click()
self.assertEqual('"Some-Name"\t"6"\t"some info"', self.assertEqual('"Some-Name"\t6\t"some info"',
pyperclip.paste()) pyperclip.paste())
def _copies_rows_with_header(self): def _copies_rows_with_header(self):
@ -87,9 +87,9 @@ class CopySelectedQueryResultsFeatureTest(BaseFeatureTest):
copy_button.click() copy_button.click()
self.assertEqual("""\"some_column"\t"value"\t"details" self.assertEqual("""\"some_column"\t"value"\t"details"
\"Some-Name"\t"6"\t"some info" \"Some-Name"\t6\t"some info"
\"Some-Other-Name"\t"22"\t"some other info" \"Some-Other-Name"\t22\t"some other info"
\"Yet-Another-Name"\t"14"\t"cool info\"""", pyperclip.paste()) \"Yet-Another-Name"\t14\t"cool info\"""", pyperclip.paste())
def _copies_columns(self): def _copies_columns(self):
pyperclip.copy("old clipboard contents") pyperclip.copy("old clipboard contents")
@ -116,7 +116,7 @@ class CopySelectedQueryResultsFeatureTest(BaseFeatureTest):
ActionChains(self.page.driver).key_down( ActionChains(self.page.driver).key_down(
Keys.CONTROL).send_keys('c').key_up(Keys.CONTROL).perform() Keys.CONTROL).send_keys('c').key_up(Keys.CONTROL).perform()
self.assertEqual('"Some-Name"\t"6"\t"some info"', self.assertEqual('"Some-Name"\t6\t"some info"',
pyperclip.paste()) pyperclip.paste())
def _copies_column_using_keyboard_shortcut(self): def _copies_column_using_keyboard_shortcut(self):
@ -154,8 +154,8 @@ class CopySelectedQueryResultsFeatureTest(BaseFeatureTest):
self.page.driver self.page.driver
).key_down(Keys.CONTROL).send_keys('c').key_up(Keys.CONTROL).perform() ).key_down(Keys.CONTROL).send_keys('c').key_up(Keys.CONTROL).perform()
self.assertEqual("""\"Some-Other-Name"\t"22" self.assertEqual(
"Yet-Another-Name"\t"14\"""", pyperclip.paste()) '"Some-Other-Name"\t22\n"Yet-Another-Name"\t14', pyperclip.paste())
def _shift_resizes_rectangular_selection(self): def _shift_resizes_rectangular_selection(self):
pyperclip.copy("old clipboard contents") pyperclip.copy("old clipboard contents")
@ -180,8 +180,8 @@ class CopySelectedQueryResultsFeatureTest(BaseFeatureTest):
Keys.CONTROL Keys.CONTROL
).send_keys('c').key_up(Keys.CONTROL).perform() ).send_keys('c').key_up(Keys.CONTROL).perform()
self.assertEqual("""\"Some-Other-Name"\t"22"\t"some other info" self.assertEqual("""\"Some-Other-Name"\t22\t"some other info"
"Yet-Another-Name"\t"14"\t"cool info\"""", pyperclip.paste()) "Yet-Another-Name"\t14\t"cool info\"""", pyperclip.paste())
def _shift_resizes_column_selection(self): def _shift_resizes_column_selection(self):
pyperclip.copy("old clipboard contents") pyperclip.copy("old clipboard contents")
@ -198,9 +198,7 @@ class CopySelectedQueryResultsFeatureTest(BaseFeatureTest):
Keys.CONTROL).send_keys('c').key_up(Keys.CONTROL).perform() Keys.CONTROL).send_keys('c').key_up(Keys.CONTROL).perform()
self.assertEqual( self.assertEqual(
"""\"Some-Name"\t"6" '"Some-Name"\t6\n"Some-Other-Name"\t22\n"Yet-Another-Name"\t14',
"Some-Other-Name"\t"22"
"Yet-Another-Name"\t"14\"""",
pyperclip.paste()) pyperclip.paste())
def _mouseup_outside_grid_still_makes_a_selection(self): def _mouseup_outside_grid_still_makes_a_selection(self):

View File

@ -60,9 +60,9 @@ class CheckFileManagerFeatureTest(BaseFeatureTest):
print("OK.", file=sys.stderr) print("OK.", file=sys.stderr)
def _navigate_to_query_tool(self): def _navigate_to_query_tool(self):
self.page.toggle_open_tree_item(self.server['name']) self.page.expand_database_node(
self.page.toggle_open_tree_item('Databases') self.server['name'],
self.page.toggle_open_tree_item(self.test_db) self.server['db_password'], self.test_db)
self.page.open_query_tool() self.page.open_query_tool()
def _create_new_file(self): def _create_new_file(self):

View File

@ -149,9 +149,9 @@ class PGDataypeFeatureTest(BaseFeatureTest):
self.page.remove_server(self.server) self.page.remove_server(self.server)
def _schema_node_expandable(self): def _schema_node_expandable(self):
self.page.toggle_open_tree_item(self.server['name']) self.page.expand_database_node(
self.page.toggle_open_tree_item('Databases') self.server['name'],
self.page.toggle_open_tree_item(self.test_db) self.server['db_password'], self.test_db)
def _check_datatype(self): def _check_datatype(self):
# Slick grid does not render all the column if viewport is not enough # Slick grid does not render all the column if viewport is not enough

View File

@ -64,9 +64,9 @@ class PGUtilitiesBackupFeatureTest(BaseFeatureTest):
test_gui_helper.close_bgprocess_popup(self) test_gui_helper.close_bgprocess_popup(self)
def runTest(self): def runTest(self):
self.page.toggle_open_server(self.server['name']) self.page.expand_database_node(
self.page.toggle_open_tree_item('Databases') self.server['name'],
self.page.toggle_open_tree_item(self.database_name) self.server['db_password'], self.database_name)
# Backup # Backup
self.page.retry_click( self.page.retry_click(
@ -115,11 +115,11 @@ class PGUtilitiesBackupFeatureTest(BaseFeatureTest):
self.assertEquals(status, "Successfully completed.") self.assertEquals(status, "Successfully completed.")
self.page.find_by_css_selector( self.page.retry_click(
NavMenuLocators.status_alertifier_more_btn_css).click() (By.CSS_SELECTOR,
NavMenuLocators.status_alertifier_more_btn_css),
self.wait.until(EC.visibility_of_element_located( (By.XPATH,
(By.XPATH, NavMenuLocators.process_watcher_alertfier))) NavMenuLocators.process_watcher_alertfier))
backup_file = None backup_file = None
# Check for XSS in Backup details # Check for XSS in Backup details
@ -143,9 +143,7 @@ class PGUtilitiesBackupFeatureTest(BaseFeatureTest):
backup_file = command[int(command.find('--file')) + backup_file = command[int(command.find('--file')) +
8:int(command.find('--host')) - 2] 8:int(command.find('--host')) - 2]
close_btn = self.page.find_by_xpath( test_gui_helper.close_process_watcher(self)
NavMenuLocators.process_watcher_close_button_xpath)
close_btn.click()
# Restore # Restore
tools_menu = self.driver.find_element_by_link_text( tools_menu = self.driver.find_element_by_link_text(
@ -186,11 +184,11 @@ class PGUtilitiesBackupFeatureTest(BaseFeatureTest):
self.assertEquals(status, "Successfully completed.") self.assertEquals(status, "Successfully completed.")
self.page.find_by_css_selector( self.page.retry_click(
NavMenuLocators.status_alertifier_more_btn_css).click() (By.CSS_SELECTOR,
NavMenuLocators.status_alertifier_more_btn_css),
self.wait.until(EC.visibility_of_element_located( (By.XPATH,
(By.XPATH, NavMenuLocators.process_watcher_alertfier))) NavMenuLocators.process_watcher_alertfier))
# Check for XSS in Restore details # Check for XSS in Restore details
if self.is_xss_check: if self.is_xss_check:
@ -206,9 +204,7 @@ class PGUtilitiesBackupFeatureTest(BaseFeatureTest):
self.assertIn("pg_restore", str(command)) self.assertIn("pg_restore", str(command))
close_watcher = self.page.find_by_xpath( test_gui_helper.close_process_watcher(self)
NavMenuLocators.process_watcher_close_button_xpath)
close_watcher.click()
if backup_file is not None: if backup_file is not None:
if os.path.isfile(backup_file): if os.path.isfile(backup_file):

View File

@ -90,20 +90,22 @@ class PGUtilitiesMaintenanceFeatureTest(BaseFeatureTest):
self.verify_command() self.verify_command()
def _open_maintenance_dialogue(self): def _open_maintenance_dialogue(self):
self.page.toggle_open_server(self.server['name']) self.page.expand_database_node(
self.page.toggle_open_tree_item('Databases') self.server['name'],
self.page.toggle_open_tree_item(self.database_name) self.server['db_password'], self.database_name)
if self.test_level == 'table': if self.test_level == 'table':
self.page.toggle_open_tree_item('Schemas') self.page.toggle_open_schema_node(self.server['name'],
self.page.toggle_open_tree_item('public') self.server['db_password'],
self.page.toggle_open_tables_node() self.database_name, 'public')
self.page.toggle_open_tables_node(self.server['name'],
self.server['db_password'],
self.database_name, 'public')
self.page.select_tree_item(self.table_name) self.page.select_tree_item(self.table_name)
self.page.retry_click( self.page.retry_click(
(By.LINK_TEXT, (By.LINK_TEXT,
NavMenuLocators.tools_menu_link_text), NavMenuLocators.tools_menu_link_text),
(By.CSS_SELECTOR, NavMenuLocators.maintenance_obj_css)) (By.CSS_SELECTOR, NavMenuLocators.maintenance_obj_css))
maintenance_obj = self.wait.until(EC.visibility_of_element_located( maintenance_obj = self.wait.until(EC.visibility_of_element_located(
(By.CSS_SELECTOR, NavMenuLocators.maintenance_obj_css))) (By.CSS_SELECTOR, NavMenuLocators.maintenance_obj_css)))
maintenance_obj.click() maintenance_obj.click()
@ -118,11 +120,12 @@ class PGUtilitiesMaintenanceFeatureTest(BaseFeatureTest):
test_gui_helper.close_bgprocess_popup(self) test_gui_helper.close_bgprocess_popup(self)
self.assertEquals(status, "Successfully completed.") self.assertEquals(status, "Successfully completed.")
self.page.find_by_css_selector(
NavMenuLocators.status_alertifier_more_btn_css).click()
self.wait.until(EC.visibility_of_element_located( self.page.retry_click(
(By.XPATH, NavMenuLocators.process_watcher_alertfier))) (By.CSS_SELECTOR,
NavMenuLocators.status_alertifier_more_btn_css),
(By.XPATH,
NavMenuLocators.process_watcher_alertfier))
command = self.page.find_by_css_selector( command = self.page.find_by_css_selector(
NavMenuLocators. NavMenuLocators.
@ -148,13 +151,12 @@ class PGUtilitiesMaintenanceFeatureTest(BaseFeatureTest):
"\nVACUUM VERBOSE" "\nVACUUM VERBOSE"
" public." + self.table_name + ";") " public." + self.table_name + ";")
self.page.find_by_xpath( test_gui_helper.close_process_watcher(self)
NavMenuLocators.process_watcher_close_button_xpath).click()
def after(self): def after(self):
test_gui_helper.close_bgprocess_popup(self) test_gui_helper.close_bgprocess_popup(self)
self.page.remove_server(self.server) self.page.remove_server(self.server)
test_utils.delete_table(self.server, self.test_db, test_utils.delete_table(self.server, self.database_name,
self.table_name) self.table_name)
connection = test_utils.get_db_connection( connection = test_utils.get_db_connection(
self.server['db'], self.server['db'],

View File

@ -56,9 +56,9 @@ class QueryToolAutoCompleteFeatureTest(BaseFeatureTest):
test_utils.create_table(self.server, self.test_db, test_utils.create_table(self.server, self.test_db,
self.second_table_name) self.second_table_name)
self.page.toggle_open_tree_item(self.server['name']) self.page.expand_database_node(
self.page.toggle_open_tree_item('Databases') self.server['name'],
self.page.toggle_open_tree_item(self.test_db) self.server['db_password'], self.test_db)
self.page.open_query_tool() self.page.open_query_tool()
self.page.wait_for_spinner_to_disappear() self.page.wait_for_spinner_to_disappear()

View File

@ -103,7 +103,7 @@ class QueryToolJourneyTest(BaseFeatureTest):
QueryToolLocators.copy_button_css) QueryToolLocators.copy_button_css)
copy_row.click() copy_row.click()
self.assertEqual('"Some-Name"\t"6"\t"some info"', self.assertEqual('"Some-Name"\t6\t"some info"',
pyperclip.paste()) pyperclip.paste())
def _test_copies_columns(self): def _test_copies_columns(self):
@ -380,9 +380,9 @@ class QueryToolJourneyTest(BaseFeatureTest):
self.page.click_modal('Yes') self.page.click_modal('Yes')
def _navigate_to_query_tool(self): def _navigate_to_query_tool(self):
self.page.toggle_open_tree_item(self.server['name']) self.page.expand_database_node(
self.page.toggle_open_tree_item('Databases') self.server['name'],
self.page.toggle_open_tree_item(self.test_db) self.server['db_password'], self.test_db)
self.page.open_query_tool() self.page.open_query_tool()
self.page.wait_for_spinner_to_disappear() self.page.wait_for_spinner_to_disappear()

View File

@ -35,9 +35,9 @@ class QueryToolFeatureTest(BaseFeatureTest):
def before(self): def before(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)
self.page.toggle_open_tree_item(self.server['name']) self.page.expand_database_node(
self.page.toggle_open_tree_item('Databases') self.server['name'],
self.page.toggle_open_tree_item(self.test_db) self.server['db_password'], self.test_db)
self.page.open_query_tool() self.page.open_query_tool()
self.page.wait_for_spinner_to_disappear() self.page.wait_for_spinner_to_disappear()
self._reset_options() self._reset_options()
@ -254,7 +254,7 @@ SELECT generate_series(1, {}) as id1, 'dummy' as id2""".format(
) )
# Table height takes some time to update, for which their is no # Table height takes some time to update, for which their is no
# particular way # particular way
time.sleep(1) time.sleep(2)
if canvas_ele.size['height'] == scrolling_height: if canvas_ele.size['height'] == scrolling_height:
break break
else: else:

View File

@ -32,12 +32,12 @@ class TableDdlFeatureTest(BaseFeatureTest):
test_utils.create_table(self.server, self.test_db, test_utils.create_table(self.server, self.test_db,
self.test_table_name) self.test_table_name)
self.page.toggle_open_server(self.server['name']) self.page.expand_database_node(
self.page.toggle_open_tree_item('Databases') self.server['name'],
self.page.toggle_open_tree_item(self.test_db) self.server['db_password'], self.test_db)
self.page.toggle_open_tree_item('Schemas') self.page.toggle_open_tables_node(
self.page.toggle_open_tree_item('public') self.server['name'], self.server['db_password'],
self.page.toggle_open_tree_item('Tables') self.test_db, 'public')
self.page.select_tree_item(self.test_table_name) self.page.select_tree_item(self.test_table_name)
self.page.click_tab("SQL") self.page.click_tab("SQL")

View File

@ -122,12 +122,12 @@ CREATE TABLE public.nonintpkey
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)
self.page.toggle_open_tree_item(self.server['name']) self.page.expand_database_node(
self.page.toggle_open_tree_item('Databases') self.server['name'],
self.page.toggle_open_tree_item(self.test_db) self.server['db_password'], self.test_db)
self.page.toggle_open_tree_item('Schemas') self.page.toggle_open_tables_node(self.server['name'],
self.page.toggle_open_tree_item('public') self.server['db_password'],
self.page.toggle_open_tree_item('Tables') self.test_db, 'public')
self._load_config_data('table_insert_update_cases') self._load_config_data('table_insert_update_cases')
# iterate on both tables # iterate on both tables
@ -349,13 +349,13 @@ CREATE TABLE public.nonintpkey
element = result_row.find_element_by_class_name("r" + str(idx)) element = result_row.find_element_by_class_name("r" + str(idx))
self.page.driver.execute_script( self.page.driver.execute_script(
"arguments[0].scrollIntoView(false)", element) "arguments[0].scrollIntoView(false)", element)
time.sleep(0.4)
self.assertEquals(element.text, config_check_data[str(idx)][1])
self.assertEquals(element.text, config_check_data[str(idx)][1]) self.assertEquals(element.text, config_check_data[str(idx)][1])
# scroll browser back to the left # scroll browser back to the left
# to reset position so other assertions can succeed # to reset position so other assertions can succeed
for idx in reversed(list(config_check_data.keys())): for idx in reversed(list(config_check_data.keys())):
time.sleep(0.4)
element = result_row.find_element_by_class_name("r" + str(idx)) element = result_row.find_element_by_class_name("r" + str(idx))
self.page.driver.execute_script( self.page.driver.execute_script(
"arguments[0].scrollIntoView(false)", element) "arguments[0].scrollIntoView(false)", element)

View File

@ -94,12 +94,12 @@ class CheckForXssFeatureTest(BaseFeatureTest):
self.server, self.test_db, self.test_table_name) self.server, self.test_db, self.test_table_name)
def _tables_node_expandable(self): def _tables_node_expandable(self):
self.page.toggle_open_server(self.server['name']) self.page.expand_database_node(
self.page.toggle_open_tree_item('Databases') self.server['name'],
self.page.toggle_open_tree_item(self.test_db) self.server['db_password'], self.test_db)
self.page.toggle_open_tree_item('Schemas') self.page.toggle_open_tables_node(self.server['name'],
self.page.toggle_open_tree_item('public') self.server['db_password'],
self.page.toggle_open_tree_item('Tables') self.test_db, 'public')
self.page.select_tree_item(self.test_table_name) self.page.select_tree_item(self.test_table_name)
def _check_xss_in_browser_tree(self): def _check_xss_in_browser_tree(self):

View File

@ -39,10 +39,10 @@ class CheckDebuggerForXssFeatureTest(BaseFeatureTest):
self.function_name = "a_test_function" + \ self.function_name = "a_test_function" + \
str(random.randint(10000, 65535)) str(random.randint(10000, 65535))
test_utils.create_debug_function( test_utils.create_debug_function(
self.server, "postgres", self.function_name self.server, self.test_db, self.function_name
) )
if test_utils.does_function_exist(self.server, 'postgres', if test_utils.does_function_exist(self.server, self.test_db,
self.function_name) != 'True': self.function_name) != 'True':
raise Exception("The required function is not found") raise Exception("The required function is not found")
@ -54,15 +54,16 @@ class CheckDebuggerForXssFeatureTest(BaseFeatureTest):
def after(self): def after(self):
self.page.remove_server(self.server) self.page.remove_server(self.server)
test_utils.drop_debug_function(self.server, "postgres", test_utils.drop_debug_function(self.server, self.test_db,
self.function_name) self.function_name)
def _function_node_expandable(self): def _function_node_expandable(self):
self.page.toggle_open_server(self.server['name']) self.page.expand_database_node(
self.page.toggle_open_tree_item('Databases') self.server['name'],
self.page.toggle_open_tree_item('postgres') self.server['db_password'], self.test_db)
self.page.toggle_open_tree_item('Schemas') self.page.toggle_open_schema_node(self.server['name'],
self.page.toggle_open_tree_item('public') self.server['db_password'],
self.test_db, 'public')
self.page.toggle_open_function_node() self.page.toggle_open_function_node()
self.page.select_tree_item(self.function_name + "()") self.page.select_tree_item(self.function_name + "()")

View File

@ -58,7 +58,8 @@ class CheckRoleMembershipControlFeatureTest(BaseFeatureTest):
"<h1>test</h1>") "<h1>test</h1>")
def _role_node_expandable(self, role): def _role_node_expandable(self, role):
self.page.toggle_open_server(self.server['name']) self.page.expand_server_node(
self.server['name'], self.server['db_password'])
self.page.toggle_open_tree_item('Login/Group Roles') self.page.toggle_open_tree_item('Login/Group Roles')
self.page.select_tree_item(role) self.page.select_tree_item(role)
@ -93,6 +94,6 @@ class CheckRoleMembershipControlFeatureTest(BaseFeatureTest):
"""This will click and open membership tab of role""" """This will click and open membership tab of role"""
self.page.retry_click( self.page.retry_click(
(By.XPATH, (By.LINK_TEXT,
"//a[normalize-space(text())='Membership']"), "Membership"),
(By.XPATH, "//input[@placeholder='Select members']")) (By.XPATH, "//input[@placeholder='Select members']"))

View File

@ -87,7 +87,7 @@ class NavMenuLocators:
".bg-process-details .bg-detailed-desc" ".bg-process-details .bg-detailed-desc"
process_watcher_close_button_xpath = \ process_watcher_close_button_xpath = \
"//div[contains(@class,'wcFloatingFocus')]//" \ "//div[contains(@class,'wcFloating')]//" \
"div[contains(@class,'fa-close')]" "div[contains(@class,'fa-close')]"
restore_file_name_xpath = "//div[contains(text(),'Restore')]" \ restore_file_name_xpath = "//div[contains(text(),'Restore')]" \
@ -227,3 +227,20 @@ class QueryToolLocators:
read_only_column_icon_xpath = "//div[contains(@class," \ read_only_column_icon_xpath = "//div[contains(@class," \
" 'editable-column-header-icon')]" \ " 'editable-column-header-icon')]" \
"/i[contains(@class, 'fa-lock')]" "/i[contains(@class, 'fa-lock')]"
class ConnectToServerDiv:
# This will contain xpaths for element relating to Connect to server div
password_field = "//input[@id='password']"
ok_button = \
"//div [@class='alertify ajs-modeless ajs-movable ajs-zoom']" \
"//button[text()='OK']"
error_message = \
"//form[@id='frmPassword']/div/div//div[@class='alert-text']"
cancel_button = \
"//div [@class='alertify ajs-modeless ajs-movable ajs-zoom']" \
"//button[text()='Cancel']"

View File

@ -21,7 +21,7 @@ from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.common.by import By from selenium.webdriver.common.by import By
from regression.feature_utils.locators import QueryToolLocators, \ from regression.feature_utils.locators import QueryToolLocators, \
NavMenuLocators NavMenuLocators, ConnectToServerDiv
from regression.feature_utils.tree_area_locators import TreeAreaLocators from regression.feature_utils.tree_area_locators import TreeAreaLocators
@ -223,7 +223,7 @@ class PgadminPage:
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)
delete_menu_item = self.find_by_partial_link_text("Delete/Drop") delete_menu_item = self.find_by_partial_link_text("Remove Server")
self.click_element(delete_menu_item) self.click_element(delete_menu_item)
self.click_modal('OK') self.click_modal('OK')
@ -245,14 +245,6 @@ class PgadminPage:
if attempts == 0: if attempts == 0:
raise Exception(e) raise Exception(e)
def get_expansion_status_of_node(self, xpath_node):
"""get the expansion status for a node through xpath"""
node_is_expanded = False
element = self.find_by_xpath(xpath_node)
if element.get_attribute("aria-expanded") == 'true':
node_is_expanded = True
return node_is_expanded
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"""
is_expanded = False is_expanded = False
@ -280,50 +272,238 @@ class PgadminPage:
file=sys.stderr) file=sys.stderr)
return is_expanded return is_expanded
def toggle_open_tree_item(self, tree_item_text): def expand_server_node(self, server_name, server_password):
# 'sleep' here helps in cases where underlying nodes are auto opened. """will expand a particular server node"""
# Otherwise, encountered situations where False value is returned server_node_expansion_status = False
# even if the underlying node to be clicked was Opened. if self.toggle_open_servers_group():
time.sleep(.6) if self.wait_for_elements_to_appear(
item_with_text = self.find_by_xpath( self.driver,
TreeAreaLocators.specified_tree_node.format(tree_item_text)) TreeAreaLocators.server_group_sub_nodes):
subnodes_of_servers = self.find_by_xpath_list(
TreeAreaLocators.server_group_sub_nodes)
subnodes_of_servers_expansion_status = \
self.find_by_xpath_list(
TreeAreaLocators.
server_group_sub_nodes_exp_status)
index_of_server_node = self.get_index_of_element(
subnodes_of_servers, server_name)
self.driver.execute_script("arguments[0].scrollIntoView()", if not self.check_server_is_connected(
item_with_text) index_of_server_node):
if self.click_and_connect_server(
subnodes_of_servers[index_of_server_node],
server_password):
server_node_expansion_status = True
else:
print(
"(expand_server_node)The server node is "
"not expanded",
file=sys.stderr)
else:
if not self.get_expansion_status_of_node_element(
subnodes_of_servers_expansion_status[
index_of_server_node]):
webdriver.ActionChains(self.driver).double_click(
subnodes_of_servers[
index_of_server_node]).perform()
if self.wait_for_elements_to_appear(
self.driver, TreeAreaLocators.
sub_nodes_of_a_server_node(server_name),
30):
server_node_expansion_status = True
else:
server_node_expansion_status = True
else:
print(
"(expand_server_node) The Servers node is"
" not expanded",
file=sys.stderr)
return server_node_expansion_status
if item_with_text.find_element_by_xpath( def expand_databases_node(self, server_name, server_password):
".//ancestor::*[@class='aciTreeLine']").get_attribute( """will expand databases node under server node"""
"aria-expanded") == 'false': databases_node_expanded = False
item = item_with_text.find_element_by_xpath( if self.expand_server_node(server_name, server_password):
".//parent::*[@class='aciTreeItem']") if self.wait_for_elements_to_appear(
ActionChains(self.driver).double_click(item).perform() self.driver,
retry = 3 TreeAreaLocators.sub_nodes_of_a_server_node(server_name)):
while retry > 0: subnodes_of_server_node = self.find_by_xpath_list(
try: TreeAreaLocators.sub_nodes_of_a_server_node(server_name))
WebDriverWait(self.driver, 5).until((lambda item_with_text: ( subnode_of_server_node_exp_status = self.find_by_xpath_list(
item_with_text.find_element_by_xpath( TreeAreaLocators.sub_nodes_of_a_server_node_exp_status(
".//ancestor::*[@class='aciTreeLine']"). server_name))
get_attribute("aria-expanded") == 'true'))) index_of_databases_node = self.get_index_of_element(
break subnodes_of_server_node,
except TimeoutException: "Databases")
retry -= 1 time.sleep(2)
pass expansion_status = self.get_expansion_status_of_node_element(
subnode_of_server_node_exp_status[index_of_databases_node])
if not expansion_status:
retry = 5
while retry > 0:
webdriver.ActionChains(self.driver).double_click(
subnodes_of_server_node[
index_of_databases_node].find_element_by_xpath(
".//*[@class='aciTreeItem']")
).perform()
if self.wait_for_elements_to_appear(
self.driver, TreeAreaLocators.
sub_nodes_of_databases_node(server_name), 3):
databases_node_expanded = True
break
else:
retry -= 1
else:
databases_node_expanded = True
else:
print("The server/previous nodes not expanded",
file=sys.stderr)
return databases_node_expanded
def toggle_open_tables_node(self): def expand_database_node(self, server_name, server_password,
"""The function will be used for opening Tables node only""" name_of_database):
"""will expand database node under databases node"""
db_node_expanded_status = False
if self.expand_databases_node(server_name, server_password):
sub_nodes_of_databases_node = self.find_by_xpath_list(
TreeAreaLocators.sub_nodes_of_databases_node(server_name))
index_of_required_db_node = self.get_index_of_element(
sub_nodes_of_databases_node,
name_of_database)
expansion_status = self.get_expansion_status_of_node_element(
self.find_by_xpath_list(
TreeAreaLocators.
sub_nodes_of_databases_node_exp_status(
server_name))[
index_of_required_db_node])
if not expansion_status:
self.driver.execute_script("arguments[0].scrollIntoView()",
sub_nodes_of_databases_node[
index_of_required_db_node])
webdriver.ActionChains(self.driver).double_click(
sub_nodes_of_databases_node[
index_of_required_db_node]).perform()
if self.wait_for_elements_to_appear(
self.driver, TreeAreaLocators.
sub_nodes_of_database_node(
name_of_database)):
db_node_expanded_status = True
else:
db_node_expanded_status = True
else:
print("The databases/previous nodes not expanded",
file=sys.stderr)
return db_node_expanded_status
# get the element which contains 'aria-expanded' info def toggle_open_schemas_node(self, server_name, server_password,
tables_expansion_ele = self.find_by_xpath("//div[div[div[div[div[div" name_of_database):
"[div[div[span[span[" """will expand schemas node under a db node"""
"(@class='aciTreeText') and " expansion_status = False
"text()='Tables']]]]]]]]]]") if self.expand_database_node(server_name, server_password,
name_of_database):
sub_nodes_db_node = self.find_by_xpath_list(
TreeAreaLocators.sub_nodes_of_database_node(
name_of_database))
index_of_schemas_node = self.get_index_of_element(
sub_nodes_db_node, "Schemas")
expansion_status = self.get_expansion_status_of_node_element(
self.find_by_xpath_list(
TreeAreaLocators.sub_nodes_of_database_node_exp_status(
name_of_database))[
index_of_schemas_node])
if not expansion_status:
self.driver.execute_script(
"arguments[0].scrollIntoView()",
sub_nodes_db_node[index_of_schemas_node])
webdriver.ActionChains(self.driver).double_click(
sub_nodes_db_node[index_of_schemas_node]).perform()
if self.wait_for_elements_to_appear(
self.driver, TreeAreaLocators.
sub_nodes_of_schemas_node(name_of_database)):
expansion_status = True
else:
expansion_status = True
else:
print(
"(expand_schemas_node) database/previous nodes "
"are not expanded",
file=sys.stderr)
return expansion_status
if tables_expansion_ele.get_attribute('aria-expanded') == 'false': def toggle_open_schema_node(
# button element of the Tables node to open it self, server_name, server_password,
item_button = self.find_by_xpath( name_of_database, name_of_schema_node):
"//div[span[span[(@class='aciTreeText') and text()" """will expand schema node under schemas node"""
"='Tables']]]/span[@class='aciTreeButton']") expansion_status = False
ActionChains(self.driver).click(item_button).perform() if self.toggle_open_schemas_node(
server_name, server_password, name_of_database):
sub_nodes_schemas_node = self.find_by_xpath_list(
TreeAreaLocators.sub_nodes_of_schemas_node(
name_of_database))
index_of_schema_node = self.get_index_of_element(
sub_nodes_schemas_node,
name_of_schema_node)
expansion_status = self.get_expansion_status_of_node_element(
self.find_by_xpath_list(
TreeAreaLocators.sub_nodes_of_schemas_node_exp_status(
name_of_database))[
index_of_schema_node])
if not expansion_status:
self.driver.execute_script(
"arguments[0].scrollIntoView()",
sub_nodes_schemas_node[index_of_schema_node])
webdriver.ActionChains(self.driver).double_click(
sub_nodes_schemas_node[index_of_schema_node]).perform()
if self.wait_for_elements_to_appear(
self.driver, TreeAreaLocators.
sub_nodes_of_schema_node(name_of_database)):
expansion_status = True
else:
expansion_status = True
else:
print(
"(expand_schema_node) schema/previous nodes are"
" not expanded",
file=sys.stderr)
return expansion_status
def toggle_open_tables_node(
self, server_name, server_password,
name_of_database, name_of_schema_node):
"""will expand tables node under schema node"""
node_expanded_successfully = False
if self.toggle_open_schema_node(
server_name, server_password, name_of_database,
name_of_schema_node):
sub_nodes_of_schema_node = self.find_by_xpath_list(
TreeAreaLocators.sub_nodes_of_schema_node(
name_of_database))
sub_nodes_of_schema_node_exp_status = self.find_by_xpath_list(
TreeAreaLocators.sub_nodes_of_schema_node_exp_status(
name_of_database))
index_of_tables_node = self.get_index_of_element(
sub_nodes_of_schema_node, "Tables")
expansion_status = self.get_expansion_status_of_node_element(
sub_nodes_of_schema_node_exp_status[index_of_tables_node])
if not expansion_status:
self.driver.execute_script("arguments[0].scrollIntoView()",
sub_nodes_of_schema_node[
index_of_tables_node])
webdriver.ActionChains(self.driver).double_click(
sub_nodes_of_schema_node[
index_of_tables_node]).perform()
if self.wait_for_elements_to_appear(
self.driver, TreeAreaLocators.
sub_nodes_of_tables_node):
node_expanded_successfully = True
else:
node_expanded_successfully = True
else:
print(
"(expand_tables_node) schema/previous nodes "
"are not expanded",
file=sys.stderr)
return node_expanded_successfully
def toggle_open_function_node(self): def toggle_open_function_node(self):
"""The function will be used for opening Functions node only""" """The function will be used for opening Functions node only"""
@ -379,6 +559,124 @@ class PgadminPage:
else: else:
node_expanded = True node_expanded = True
def check_server_is_connected(self, index_of_server):
"""This will check connected status of a server, as connection
status is contained either in span or div element so checking it"""
server_connected = False
try:
connection_status_elements = self.find_by_xpath_list(
TreeAreaLocators.server_group_sub_nodes_connected_status)
span_elements = connection_status_elements[
index_of_server].find_elements_by_tag_name("span")
div_elements = connection_status_elements[
index_of_server].find_elements_by_tag_name("div")
span_value_of_class_att = ""
div_value_of_class_att = ""
if len(span_elements) > 0:
span_value_of_class_att = \
span_elements[0].get_attribute('class')
if len(div_elements) > 0:
div_value_of_class_att = \
div_elements[0].get_attribute('class')
if (("aciTreeIcon icon-pg" in span_value_of_class_att or
"aciTreeIcon icon-pg" in div_value_of_class_att or
"aciTreeIcon icon-ppas" in
span_value_of_class_att or
"aciTreeIcon icon-ppas" in div_value_of_class_att) and
("aciTreeIcon icon-server-not-connected" not in
span_value_of_class_att or
"aciTreeIcon icon-server-not-connected" not in
div_value_of_class_att)):
server_connected = True
except Exception as e:
print("There is some exception thrown in the function "
"check_server_is_connected and is: " + str(e),
file=sys.stderr)
return server_connected
def click_and_connect_server(self, server_element, password):
"""will connect a server node, will provide the password in the
respective window"""
server_connection_status = False
try:
webdriver.ActionChains(self.driver).double_click(
server_element).perform()
if self.wait_for_element_to_appear(self.driver,
ConnectToServerDiv.ok_button):
self.fill_input_by_xpath(
ConnectToServerDiv.password_field, password)
self.find_by_xpath(ConnectToServerDiv.ok_button).click()
self.wait_until_element_not_visible(
ConnectToServerDiv.ok_button)
if self.wait_for_element_to_be_visible(
self.driver, ConnectToServerDiv.error_message, 2):
print(
"While entering password in click_and_connect_server "
"function, error is occurred : " + str(
self.find_by_xpath(
ConnectToServerDiv.error_message).text),
file=sys.stderr)
else:
server_connection_status = True
except Exception as e:
print(
"There is some exception thrown click_and_connect_server "
"and is: " + str(
e), file=sys.stderr)
return server_connection_status
def get_expansion_status_of_node(self, xpath_node):
"""get the expansion status for a node through xpath"""
node_is_expanded = False
element = self.find_by_xpath(xpath_node)
if element.get_attribute("aria-expanded") == 'true':
node_is_expanded = True
return node_is_expanded
def get_expansion_status_of_node_element(self, element):
"""get the expansion status for an element"""
node_is_expanded = False
try:
if element.get_attribute("aria-expanded") == 'true':
node_is_expanded = True
except Exception as e:
print(
"There is some exception thrown in the function "
"get_expansion_status_of_node_element and is: " + str(
e), file=sys.stderr)
return node_is_expanded
def toggle_open_tree_item(self, tree_item_text):
# '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(
TreeAreaLocators.specified_tree_node.format(tree_item_text))
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()
retry = 3
while retry > 0:
try:
WebDriverWait(self.driver, 5).until((lambda item_with_text: (
item_with_text.find_element_by_xpath(
".//ancestor::*[@class='aciTreeLine']").
get_attribute("aria-expanded") == 'true')))
break
except TimeoutException:
retry -= 1
pass
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:
@ -692,6 +990,19 @@ class PgadminPage:
return self._wait_for("element to exist", element_if_it_exists) return self._wait_for("element to exist", element_if_it_exists)
def wait_for_elements_to_appear(self, driver, locator, time_value=20):
"""This will wait until list of elements or an element is visible,
The time out value is userdefined"""
elements_located_status = False
try:
if WebDriverWait(driver, time_value).until(
EC.visibility_of_any_elements_located((
By.XPATH, locator))):
elements_located_status = True
except Exception as e:
pass
return elements_located_status
def find_by_xpath_list(self, xpath): def find_by_xpath_list(self, xpath):
"""This will find out list of elements through a single xpath""" """This will find out list of elements through a single xpath"""
return self.wait_for_elements( return self.wait_for_elements(
@ -749,11 +1060,11 @@ class PgadminPage:
click_status = False click_status = False
attempt = 0 attempt = 0
while click_status is not True and attempt < 5: while click_status is not True and attempt < 10:
try: try:
element = self.driver.find_element(*click_locator) element = self.driver.find_element(*click_locator)
element.click() element.click()
WebDriverWait(self.driver, 5).until( WebDriverWait(self.driver, 2).until(
EC.visibility_of_element_located(verify_locator)) EC.visibility_of_element_located(verify_locator))
click_status = True click_status = True
except Exception: except Exception:

View File

@ -26,6 +26,98 @@ class TreeAreaLocators():
"following-sibling::ul/li/div/div/div/span[2]/" \ "following-sibling::ul/li/div/div/div/span[2]/" \
"span[@class='aciTreeText']" "span[@class='aciTreeText']"
server_group_sub_nodes_exp_status = \
"//div[div[span[span[contains(text(),'Servers')]]]]" \
"/following-sibling::ul/li/div"
server_group_sub_nodes_connected_status = \
"//div[div[span[span[contains(text(), 'Servers')]]]]/" \
"following-sibling::ul/li/div/div/div/span[2]"
specified_tree_node = \ specified_tree_node = \
"//div[@id='tree']//span[@class='aciTreeItem']/" \ "//div[@id='tree']//span[@class='aciTreeItem']/" \
"span[(@class='aciTreeText') and text()='{}']" "span[(@class='aciTreeText') and text()='{}']"
specified_tree_node_exp_status = \
"//div[@id='tree']//span[@class='aciTreeItem']/" \
"span[(@class='aciTreeText') and text()='{}']" \
"//ancestor::*[@class='aciTreeLine']"
sub_nodes_of_tables_node = \
"//div[div[div[div[div[div[div[div[span[span[" \
"contains(text(),'Tables')]]]]]]]]]]/" \
"following-sibling::ul/li/div//div/span[2]/span[2]"
@staticmethod
def sub_nodes_of_a_server_node(server_name):
xpath = "//div[div[div[span[span[contains(text(),'%s')]]]]]/" \
"following-sibling::ul/li/div[@class='aciTreeLine']" % \
server_name
return xpath
@staticmethod
def sub_nodes_of_a_server_node_exp_status(server_name):
xpath = "//div[div[div[span[span[contains(text(),'%s')]]]]]/" \
"following-sibling::ul/li/div" % server_name
return xpath
@staticmethod
def databases_node_of_a_server_node(server_name):
xpath = "//div[div[div[span[span[contains(text(),'%s')]]]]]/" \
"following-sibling::ul/li/div/div/div/div/span[2]/span[2 " \
"and text()='Databases ']" % server_name
return xpath
@staticmethod
def sub_nodes_of_databases_node(server_name):
xpath = "//div[div[div[span[span[contains(text(),'%s')]]]]]/" \
"following-sibling::ul/li[1]/div/following-sibling::ul/li/" \
"div/div/div/div/div/span[2]/span[@class='aciTreeText']" % \
server_name
return xpath
@staticmethod
def sub_nodes_of_databases_node_exp_status(server_name):
xpath = "//div[div[div[span[span[contains(text(), '%s')]]]]]/" \
"following-sibling::ul/li[1]/div/following-sibling::ul/li/" \
"div" % server_name
return xpath
@staticmethod
def sub_nodes_of_database_node(database_name):
xpath = "//div[div[div[div[div[span[span[contains(text()," \
"'%s')]]]]]]]/following-sibling::ul/li/div/div/div/div/div/" \
"div/span[2]/span[2]" % database_name
return xpath
@staticmethod
def sub_nodes_of_database_node_exp_status(database_name):
xpath = "//div[div[div[div[div[span[span[contains(text(), " \
"'%s')]]]]]]]/following-sibling::ul/li/div" % database_name
return xpath
@staticmethod
def sub_nodes_of_schemas_node(database_name):
xpath = "//div[div[div[div[div[span[span[text()='%s']]]]]]]/" \
"following-sibling::ul/li[7]/ul/li/div//div/span/" \
"span[@class='aciTreeText']" % database_name
return xpath
@staticmethod
def sub_nodes_of_schemas_node_exp_status(database_name):
xpath = "//div[div[div[div[div[span[span[text()='%s']]]]]]]/" \
"following-sibling::ul/li[7]/ul/li/div" % database_name
return xpath
@staticmethod
def sub_nodes_of_schema_node(database_name):
xpath = "//div[div[div[div[div[span[span[text()='%s']]]]]]]/" \
"following-sibling::ul/li[7]/ul/li/ul/li/div//div/" \
"span[2]/span[2]" % database_name
return xpath
@staticmethod
def sub_nodes_of_schema_node_exp_status(database_name):
xpath = "//div[div[div[div[div[span[span[text()='%s']]]]]]]/" \
"following-sibling::ul/li[7]/ul/li/ul/li/div" % database_name
return xpath

View File

@ -6,6 +6,7 @@
# This software is released under the PostgreSQL Licence # This software is released under the PostgreSQL Licence
# #
########################################################################## ##########################################################################
from regression.feature_utils.locators import NavMenuLocators
def close_bgprocess_popup(tester): def close_bgprocess_popup(tester):
@ -41,3 +42,16 @@ def close_bgprocess_popup(tester):
except Exception: except Exception:
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()
def close_process_watcher(tester):
attempt = 5
while attempt > 0:
close_btn = tester.page.find_by_xpath(
NavMenuLocators.process_watcher_close_button_xpath)
close_btn.click()
if not tester.page.check_if_element_exist_by_xpath(
NavMenuLocators.process_watcher_close_button_xpath, 1):
break
else:
attempt -= 1