Feature test improvement and fix intermittent failures part of #3936

This commit is contained in:
Shubham Agarwal
2019-08-22 14:50:51 +05:30
committed by Akshay Joshi
parent 7090c02014
commit 9f455a514e
21 changed files with 1213 additions and 726 deletions

View File

@@ -10,9 +10,8 @@
from __future__ import print_function
import sys
import random
import time
from regression.python_test_utils import test_utils
from regression.feature_utils.locators import BrowserToolBarLocators
from regression.feature_utils.base_feature_test import BaseFeatureTest
from selenium.common.exceptions import TimeoutException, \
StaleElementReferenceException
@@ -57,27 +56,25 @@ class BrowserToolBarFeatureTest(BaseFeatureTest):
def after(self):
self.page.remove_server(self.server)
test_utils.delete_table(self.server, self.test_db,
self.test_table_name)
def _locate_database_tree_node(self):
def test_query_tool_button(self):
self.page.toggle_open_tree_item(self.server['name'])
self.page.toggle_open_tree_item('Databases')
self.page.toggle_open_tree_item(self.test_db)
def test_query_tool_button(self):
self._locate_database_tree_node()
retry_count = 0
while retry_count < 5:
try:
self.page.find_by_css_selector(
".wcFrameButton[title='Query Tool']:not(.disabled)")\
BrowserToolBarLocators.open_query_tool_button_css)\
.click()
break
except StaleElementReferenceException:
except (StaleElementReferenceException, TimeoutException):
retry_count += 1
time.sleep(0.5)
self.page.find_by_css_selector(".wcPanelTab .wcTabIcon.fa.fa-bolt")
self.page.find_by_css_selector(
BrowserToolBarLocators.query_tool_panel_css)
def test_view_data_tool_button(self):
self.page.select_tree_item(self.test_db)
@@ -90,26 +87,23 @@ class BrowserToolBarFeatureTest(BaseFeatureTest):
while retry_count < 5:
try:
self.page.find_by_css_selector(
".wcFrameButton[title='View Data']:not(.disabled)").click()
BrowserToolBarLocators.view_table_data_button_css).click()
break
except StaleElementReferenceException:
except (StaleElementReferenceException, TimeoutException):
retry_count += 1
time.sleep(0.5)
self.page.find_by_css_selector(".wcPanelTab .wcTabIcon.fa.fa-bolt")
self.page.find_by_css_selector(
BrowserToolBarLocators.view_data_panel_css)
def test_filtered_rows_tool_button(self):
retry_count = 0
while retry_count < 5:
try:
self.page.find_by_css_selector(
".wcFrameButton[title='Filtered Rows']:not(.disabled)")\
BrowserToolBarLocators.filter_data_button_css)\
.click()
break
except StaleElementReferenceException:
except (StaleElementReferenceException, TimeoutException):
retry_count += 1
time.sleep(0.5)
self.page.find_by_css_selector(
".alertify .ajs-header[data-title~='Filter']")
BrowserToolBarLocators.filter_alertify_box_css)
self.page.click_modal('Cancel')

View File

@@ -9,11 +9,11 @@
import pyperclip
import random
from selenium.webdriver import ActionChains
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 regression.feature_utils.locators import QueryToolLocators
class CopySelectedQueryResultsFeatureTest(BaseFeatureTest):
@@ -32,10 +32,9 @@ class CopySelectedQueryResultsFeatureTest(BaseFeatureTest):
# Create test table with random name to avoid same name conflicts in
# parallel execution
self.test_table_name = "test_table" + str(random.randint(1000, 3000))
self.page.add_server(self.server)
test_utils.create_table(
self.server, self.test_db, self.test_table_name)
self.page.add_server(self.server)
def runTest(self):
self.page.toggle_open_tree_item(self.server['name'])
@@ -46,7 +45,8 @@ class CopySelectedQueryResultsFeatureTest(BaseFeatureTest):
self.page.fill_codemirror_area_with(
"SELECT * FROM %s ORDER BY some_column" % self.test_table_name)
self.page.find_by_id("btn-flash").click()
self.page.find_by_css_selector(
QueryToolLocators.btn_execute_query_css).click()
self._copies_rows()
self._copies_columns()
@@ -59,21 +59,26 @@ class CopySelectedQueryResultsFeatureTest(BaseFeatureTest):
def _copies_rows(self):
pyperclip.copy("old clipboard contents")
self.page.find_by_xpath(
"//*[contains(@class, 'slick-row')]/*[1]").click()
first_row = self.page.find_by_xpath(
QueryToolLocators.output_row_xpath.format(1))
first_row.click()
self.page.find_by_xpath("//*[@id='btn-copy-row']").click()
copy_button = self.page.find_by_css_selector(
QueryToolLocators.copy_button_css)
copy_button.click()
self.assertEqual('"Some-Name"\t"6"\t"some info"',
pyperclip.paste())
def _copies_columns(self):
pyperclip.copy("old clipboard contents")
self.page.find_by_xpath(
"//*[@data-test='output-column-header' and "
"contains(., 'some_column')]"
).click()
self.page.find_by_xpath("//*[@id='btn-copy-row']").click()
column = self.page.find_by_css_selector(
QueryToolLocators.output_column_header_css.format('some_column'))
column.click()
copy_button = self.page.find_by_css_selector(
QueryToolLocators.copy_button_css)
copy_button.click()
self.assertEqual(
"""\"Some-Name"
@@ -83,8 +88,9 @@ class CopySelectedQueryResultsFeatureTest(BaseFeatureTest):
def _copies_row_using_keyboard_shortcut(self):
pyperclip.copy("old clipboard contents")
self.page.find_by_xpath(
"//*[contains(@class, 'slick-row')]/*[1]").click()
first_row = self.page.find_by_xpath(
QueryToolLocators.output_row_xpath.format(1))
first_row.click()
ActionChains(self.page.driver).key_down(
Keys.CONTROL).send_keys('c').key_up(Keys.CONTROL).perform()
@@ -94,10 +100,9 @@ class CopySelectedQueryResultsFeatureTest(BaseFeatureTest):
def _copies_column_using_keyboard_shortcut(self):
pyperclip.copy("old clipboard contents")
self.page.find_by_xpath(
"//*[@data-test='output-column-header' and "
"contains(., 'some_column')]"
).click()
column = self.page.find_by_css_selector(
QueryToolLocators.output_column_header_css.format('some_column'))
column.click()
ActionChains(self.page.driver).key_down(
Keys.CONTROL).send_keys('c').key_up(Keys.CONTROL).perform()
@@ -111,12 +116,12 @@ class CopySelectedQueryResultsFeatureTest(BaseFeatureTest):
def _copies_rectangular_selection(self):
pyperclip.copy("old clipboard contents")
top_left_cell = self.page.find_by_xpath(
"//div[contains(@class, 'slick-cell') and "
"contains(., 'Some-Other-Name')]"
)
top_left_cell = \
self.page.find_by_xpath(
QueryToolLocators.output_column_data_xpath.
format('Some-Other-Name'))
bottom_right_cell = self.page.find_by_xpath(
"//div[contains(@class, 'slick-cell') and contains(., '14')]")
QueryToolLocators.output_column_data_xpath.format('14'))
ActionChains(
self.page.driver
@@ -135,11 +140,11 @@ class CopySelectedQueryResultsFeatureTest(BaseFeatureTest):
pyperclip.copy("old clipboard contents")
top_left_cell = self.page.find_by_xpath(
"//div[contains(@class, 'slick-cell') and "
"contains(., 'Some-Other-Name')]"
QueryToolLocators.output_column_data_xpath.
format('Some-Other-Name')
)
initial_bottom_right_cell = self.page.find_by_xpath(
"//div[contains(@class, 'slick-cell') and contains(., '14')]")
QueryToolLocators.output_column_data_xpath.format('14'))
ActionChains(
self.page.driver
).click_and_hold(top_left_cell).move_to_element(
@@ -160,10 +165,10 @@ class CopySelectedQueryResultsFeatureTest(BaseFeatureTest):
def _shift_resizes_column_selection(self):
pyperclip.copy("old clipboard contents")
self.page.find_by_xpath(
"//*[@data-test='output-column-header' and "
"contains(., 'value')]"
).click()
column = self.page.find_by_css_selector(
QueryToolLocators.output_column_header_css.format('value')
)
column.click()
ActionChains(self.page.driver).key_down(
Keys.SHIFT).send_keys(Keys.ARROW_LEFT).key_up(Keys.SHIFT).perform()
@@ -181,11 +186,11 @@ class CopySelectedQueryResultsFeatureTest(BaseFeatureTest):
pyperclip.copy("old clipboard contents")
bottom_right_cell = self.page.find_by_xpath(
"//div[contains(@class, 'slick-cell') and "
"contains(., 'cool info')]"
QueryToolLocators.output_column_data_xpath.format('cool info')
)
load_button = self.page.find_by_xpath("//button[@id='btn-load-file']")
load_button = self.page.find_by_css_selector(
QueryToolLocators.btn_load_file_css)
ActionChains(self.page.driver).click_and_hold(bottom_right_cell) \
.move_to_element(load_button) \
.release(load_button) \
@@ -199,3 +204,5 @@ class CopySelectedQueryResultsFeatureTest(BaseFeatureTest):
def after(self):
self.page.close_query_tool()
self.page.remove_server(self.server)
test_utils.delete_table(self.server, self.test_db,
self.test_table_name)

View File

@@ -9,15 +9,16 @@
from __future__ import print_function
import os
import time
import sys
import time
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.common.by import By
from selenium.common.exceptions import StaleElementReferenceException, \
TimeoutException
from selenium.webdriver.support import expected_conditions as EC
from regression.feature_utils.base_feature_test import BaseFeatureTest
from .locators import QueryToolLocatorsCss
from regression.feature_utils.locators import QueryToolLocators
class CheckFileManagerFeatureTest(BaseFeatureTest):
@@ -65,32 +66,40 @@ class CheckFileManagerFeatureTest(BaseFeatureTest):
self.page.open_query_tool()
def _create_new_file(self):
self.page.find_by_css_selector(QueryToolLocatorsCss.btn_save_file)\
self.page.find_by_css_selector(QueryToolLocators.btn_save_file)\
.click()
# Set the XSS value in input
self.page.find_by_css_selector('.change_file_types')
self.page.fill_input_by_css_selector("input#file-input-path",
self.XSS_FILE)
self.page.fill_input_by_css_selector(
QueryToolLocators.input_file_path_css, self.XSS_FILE)
# Save the file
self.page.click_modal('Create')
self.page.wait_for_query_tool_loading_indicator_to_disappear()
def _open_file_manager_and_check_xss_file(self):
self.page.find_by_id("btn-load-file").click()
load_file = self.page.find_by_css_selector(
QueryToolLocators.btn_load_file_css)
load_file.click()
self.page.find_by_css_selector('.change_file_types')
self.page.fill_input_by_css_selector("#file-input-path", "/tmp/",
key_after_input=Keys.RETURN)
self.page.fill_input_by_css_selector(
QueryToolLocators.input_file_path_css,
"/tmp/", key_after_input=Keys.RETURN)
if self.page.driver.capabilities['browserName'] == 'firefox':
table = self.page.wait_for_element_to_reload(
lambda driver:
driver.find_element_by_css_selector("table#contents")
lambda driver: driver.find_element_by_css_selector(
QueryToolLocators.select_file_content_css)
)
else:
table = self.page.driver \
.find_element_by_css_selector("table#contents")
contents = table.get_attribute('innerHTML')
table = self.page.driver.find_element_by_css_selector(
QueryToolLocators.select_file_content_css)
retry_count = 0
while retry_count < 5:
try:
contents = table.get_attribute('innerHTML')
break
except (StaleElementReferenceException, TimeoutException):
retry_count += 1
self.page.click_modal('Cancel')
self.page.wait_for_query_tool_loading_indicator_to_disappear()
@@ -107,7 +116,9 @@ class CheckFileManagerFeatureTest(BaseFeatureTest):
) != -1, "{0} might be vulnerable to XSS ".format(source)
def _check_file_sorting(self):
self.page.find_by_id("btn-load-file").click()
load_file = self.page.find_by_css_selector(
QueryToolLocators.btn_load_file_css)
load_file.click()
self.page.find_by_css_selector("#contents th[data-column='0']")
# Added time.sleep so that the element to be clicked.
@@ -134,7 +145,7 @@ class CheckFileManagerFeatureTest(BaseFeatureTest):
if not success:
raise Exception("Unable to sort in ascending order while clicked "
"on 'Name' column")
# Added time.sleep so that the element to be clicked.
time.sleep(0.05)
# Click and Check for sort Descending
@@ -143,9 +154,10 @@ class CheckFileManagerFeatureTest(BaseFeatureTest):
iteration = 0
success = False
while not success and iteration < 4:
self.page.find_by_xpath("//th[@data-column='0']"
"/div/span[text()='Name']").click()
try:
self.page.find_by_xpath("//th[@data-column='0']"
"/div/span[text()='Name']").click()
self.wait.until(
EC.presence_of_element_located((
By.CSS_SELECTOR,

View File

@@ -15,13 +15,14 @@ from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By
from selenium.webdriver import ActionChains
from regression.feature_utils.base_feature_test import BaseFeatureTest
from selenium.webdriver.common.keys import Keys
from regression.feature_utils.base_feature_test import BaseFeatureTest
from regression.feature_utils.locators import NavMenuLocators
class KeyboardShortcutFeatureTest(BaseFeatureTest):
"""
This feature test will test the keyboard short is working
This feature test will test the keyboard shortcut is working
properly.
"""
@@ -85,23 +86,36 @@ class KeyboardShortcutFeatureTest(BaseFeatureTest):
print("OK", file=sys.stderr)
def _update_preferences(self):
self.page.find_by_id("mnu_file").click()
self.page.find_by_id("mnu_preferences").click()
file_menu = self.page.find_by_css_selector(
NavMenuLocators.file_menu_css)
file_menu.click()
pref_menu_item = self.page.find_by_css_selector(
NavMenuLocators.preference_menu_item_css)
pref_menu_item.click()
# Wait till the preference dialogue box is displayed by checking the
# visibility of Show System Object label
self.wait.until(EC.presence_of_element_located(
(By.XPATH, "//*[contains(string(), 'Show system objects?')]"))
(By.XPATH, NavMenuLocators.show_system_objects_pref_label_xpath))
)
self.page.find_by_css_selector(
".ajs-dialog.pg-el-container .ajs-maximize"
).click()
maximize_button = self.page.find_by_css_selector(
NavMenuLocators.maximize_pref_dialogue_css)
maximize_button.click()
browser = self.page.find_by_xpath(
"//*[contains(@class,'aciTreeLi') and contains(.,'Browser')]")
browser_node = self.page.find_by_xpath(
NavMenuLocators.specified_preference_tree_node.format('Browser'))
if self.page.find_by_xpath(
NavMenuLocators.specified_pref_node_exp_status.
format('Browser')).get_attribute('aria-expanded') == 'false':
browser.find_element_by_xpath(
"//*[contains(@class,'aciTreeText') and "
"contains(.,'Keyboard shortcuts')]").click()
ActionChains(self.driver).double_click(browser_node).perform()
keyboard_node = self.page.find_by_xpath(
NavMenuLocators.specified_sub_node_of_pref_tree_node.format(
'Browser', 'Keyboard shortcuts'))
keyboard_node.click()
for s in self.new_shortcuts:
key = self.new_shortcuts[s]['shortcut'][2]

View File

@@ -1,32 +0,0 @@
class QueryToolLocatorsCss:
btn_save_file = "#btn-save-file"
btn_save_data = "#btn-save-data"
btn_execute_query = "#btn-flash"
btn_query_dropdown = "#btn-query-dropdown"
btn_auto_rollback = "#btn-auto-rollback"
btn_auto_rollback_check_status = "#btn-auto-rollback > i"
btn_auto_commit = "#btn-auto-commit"
btn_auto_commit_check_status = "#btn-auto-commit > i"
btn_cancel_query = "#btn-cancel-query"
btn_explain = "#btn-explain"
btn_explain_analyze = "#btn-explain-analyze"
btn_explain_options_dropdown = "#btn-explain-options-dropdown"
btn_explain_verbose = "#btn-explain-verbose"
btn_explain_costs = "#btn-explain-costs"
btn_explain_buffers = "#btn-explain-buffers"
btn_explain_timing = "#btn-explain-timing"
btn_clear_dropdown = "#btn-clear-dropdown"
btn_clear = "#btn-clear"
btn_commit = "#btn-commit"
query_editor_panel = "#output-panel"
query_history_selected = "#query_list .selected"
query_history_selected_icon = '#query_list .selected #query_source_icon'
query_history_detail = "#query_detail"
query_history_generated_queries_toggle = '#generated-queries-toggle'
editor_panel = "#output-panel"
query_messages_panel = ".sql-editor-message"
execute_icon = "fa-bolt"
explain_icon = "fa-hand-pointer-o"
explain_analyze_icon = "fa-list-alt"
save_data_icon = "icon-save-data-changes"
commit_icon = "icon-commit"

View File

@@ -18,6 +18,8 @@ from selenium.webdriver.common.by import By
from selenium.webdriver import ActionChains
from regression.python_test_utils import test_utils
from regression.feature_utils.base_feature_test import BaseFeatureTest
from regression.feature_utils.locators import NavMenuLocators, \
QueryToolLocators
CURRENT_PATH = os.path.dirname(os.path.realpath(__file__))
@@ -78,35 +80,42 @@ class PGDataypeFeatureTest(BaseFeatureTest):
connection.close()
def _update_preferences(self):
self.page.find_by_id("mnu_file").click()
self.page.find_by_id("mnu_preferences").click()
file_menu = self.page.find_by_css_selector(
NavMenuLocators.file_menu_css)
file_menu.click()
pref_menu_item = self.page.find_by_css_selector(
NavMenuLocators.preference_menu_item_css)
pref_menu_item.click()
wait = WebDriverWait(self.page.driver, 10)
# Wait till the preference dialogue box is displayed by checking the
# visibility of Show System Object label
wait.until(EC.presence_of_element_located(
(By.XPATH, "//*[contains(string(), 'Show system objects?')]"))
(By.XPATH, NavMenuLocators.show_system_objects_pref_label_xpath))
)
self.page.find_by_css_selector(
".ajs-dialog.pg-el-container .ajs-maximize").click()
maximize_button = self.page.find_by_css_selector(
NavMenuLocators.maximize_pref_dialogue_css)
maximize_button.click()
sql_editor = self.page.find_by_xpath(
"//*[contains(@class,'aciTreeLi') and contains(.,'Query Tool')]")
NavMenuLocators.specified_preference_tree_node.
format('Query Tool'))
if self.page.find_by_xpath(
NavMenuLocators.specified_pref_node_exp_status.
format('Query Tool')).\
get_attribute('aria-expanded') == 'false':
ActionChains(self.driver).double_click(sql_editor).perform()
sql_editor.find_element_by_xpath(
"//*[contains(@class,'aciTreeText') and contains(.,'Options')]"
).click()
option_node = self.page.find_by_xpath(
NavMenuLocators.specified_sub_node_of_pref_tree_node.format(
'Query Tool', 'Options'))
option_node.click()
insert_bracket_pairs_control = self.page.find_by_xpath(
"//div[contains(@class,'pgadmin-control-group') and "
"contains(.,'Insert bracket pairs?')]"
)
switch_btn = insert_bracket_pairs_control.\
find_element_by_class_name('toggle')
# check if switch is on then only toggle.
if 'off' not in switch_btn.get_attribute('class'):
switch_btn.click()
self.page.set_switch_box_status(
NavMenuLocators.insert_bracket_pair_switch_btn, 'No')
# save and close the preference dialog.
self.page.click_modal('Save')
@@ -121,8 +130,10 @@ class PGDataypeFeatureTest(BaseFeatureTest):
'yellow','green','blue','purple');
"""
self.page.fill_codemirror_area_with(query)
self.page.find_by_id("btn-flash").click()
self._clear_query_tool()
execute_query = self.page.find_by_css_selector(
QueryToolLocators.btn_execute_query_css)
execute_query.click()
self.page.clear_query_tool()
def runTest(self):
self.page.wait_for_spinner_to_disappear()
@@ -150,7 +161,9 @@ class PGDataypeFeatureTest(BaseFeatureTest):
for batch in config_data:
query = self.construct_select_query(batch)
self.page.fill_codemirror_area_with(query)
self.page.find_by_id("btn-flash").click()
execute_query = self.page.find_by_css_selector(
QueryToolLocators.btn_execute_query_css)
execute_query.click()
wait = WebDriverWait(self.page.driver, 5)
@@ -168,12 +181,13 @@ class PGDataypeFeatureTest(BaseFeatureTest):
))
canvas = wait.until(EC.presence_of_element_located(
(By.CSS_SELECTOR, "#datagrid .slick-viewport .grid-canvas"))
(By.CSS_SELECTOR, QueryToolLocators.query_output_canvas_css))
)
# For every sample data-type value, check the expected output.
cnt = 2
cells = canvas.find_elements_by_css_selector('.slick-cell')
cells = canvas.find_elements_by_css_selector(
QueryToolLocators.query_output_cells)
# remove first element as it is row number.
cells.pop(0)
for val, cell, datatype in zip(
@@ -202,7 +216,7 @@ class PGDataypeFeatureTest(BaseFeatureTest):
"for datatype {0}\n{1} does not match with {2}".format(
datatype, val, expected_output
)
self._clear_query_tool()
self.page.clear_query_tool()
def construct_select_query(self, batch):
query = 'SELECT '
@@ -233,18 +247,6 @@ class PGDataypeFeatureTest(BaseFeatureTest):
datatype, source_code, string_to_find
)
def _clear_query_tool(self):
self.page.click_element(
self.page.find_by_xpath("//*[@id='btn-clear-dropdown']")
)
ActionChains(self.driver)\
.move_to_element(self.page.find_by_xpath("//*[@id='btn-clear']"))\
.perform()
self.page.click_element(
self.page.find_by_xpath("//*[@id='btn-clear']")
)
self.page.click_modal('Yes')
def _is_datatype_available_in_current_database(self, datatype):
if datatype == '':
return True

View File

@@ -11,9 +11,11 @@ import os
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
from selenium.common.exceptions import ElementClickInterceptedException
from regression.feature_utils.base_feature_test import BaseFeatureTest
from regression.python_test_utils import test_utils
from regression.python_test_utils import test_gui_helper
from regression.feature_utils.locators import NavMenuLocators
class PGUtilitiesBackupFeatureTest(BaseFeatureTest):
@@ -61,22 +63,47 @@ class PGUtilitiesBackupFeatureTest(BaseFeatureTest):
self.page.toggle_open_tree_item(self.database_name)
# Backup
self.driver.find_element_by_link_text("Tools").click()
retry = 3
while retry > 0:
try:
self.driver.find_element_by_link_text(
NavMenuLocators.tools_menu_link_text).click()
break
except ElementClickInterceptedException:
retry -= 1
self.page.find_by_partial_link_text("Backup...").click()
backup_object = self.wait.until(EC.visibility_of_element_located(
(By.CSS_SELECTOR, NavMenuLocators.backup_obj_css)))
backup_object.click()
self.wait.until(EC.element_to_be_clickable(
(By.CSS_SELECTOR, ".file [name='file']")))
self.wait.until(EC.element_to_be_clickable(
(By.CSS_SELECTOR, ".file [name='file']"))).click()
# Enter the file name of the backup to be taken
self.wait.until(EC.visibility_of_element_located(
(By.NAME, NavMenuLocators.backup_filename_txt_box_name)))
element = self.wait.until(EC.element_to_be_clickable(
(By.NAME, NavMenuLocators.backup_filename_txt_box_name)))
element.click()
self.page.fill_input_by_field_name(
"file", "test_backup", loose_focus=True)
NavMenuLocators.backup_filename_txt_box_name,
"test_backup", loose_focus=True)
self.page.find_by_xpath("//button[contains(@class,'fa-save') "
"and contains(.,'Backup')]").click()
# Click on the take Backup button
take_bckup = self.page.find_by_xpath(
NavMenuLocators.backup_btn_xpath)
click = True
while click:
try:
take_bckup.click()
if self.page.wait_for_element_to_disappear(
lambda driver: driver.find_element_by_name(
NavMenuLocators.backup_filename_txt_box_name)):
click = False
except Exception as e:
pass
self.page.find_by_css_selector('.ajs-bg-bgprocess')
# Wait for the backup status alertfier
self.wait.until(EC.visibility_of_element_located(
(By.CSS_SELECTOR,
NavMenuLocators.bcg_process_status_alertifier_css)))
status = test_utils.get_watcher_dialogue_status(self)
@@ -86,7 +113,10 @@ class PGUtilitiesBackupFeatureTest(BaseFeatureTest):
self.assertEquals(status, "Successfully completed.")
self.page.find_by_css_selector(
".pg-bg-more-details").click()
NavMenuLocators.status_alertifier_more_btn_css).click()
self.wait.until(EC.visibility_of_element_located(
(By.XPATH, NavMenuLocators.process_watcher_alertfier)))
backup_file = None
# Check for XSS in Backup details
@@ -94,7 +124,8 @@ class PGUtilitiesBackupFeatureTest(BaseFeatureTest):
self._check_detailed_window_for_xss('Backup')
else:
command = self.page.find_by_css_selector(
".bg-process-details .bg-detailed-desc").text
NavMenuLocators.process_watcher_detailed_command_canvas_css).\
text
self.assertIn(self.server['name'], str(command))
self.assertIn("from database 'pg_utility_test_db'", str(command))
@@ -109,26 +140,41 @@ class PGUtilitiesBackupFeatureTest(BaseFeatureTest):
backup_file = command[int(command.find('--file')) +
8:int(command.find('--host')) - 2]
self.page.find_by_xpath("//div[contains(@class,'wcFloatingFocus')"
"]//div[contains(@class,'fa-close')]").click()
close_btn = self.page.find_by_xpath(
NavMenuLocators.process_watcher_close_button_xpath)
close_btn.click()
# Restore
self.driver.find_element_by_link_text("Tools").click()
self.page.find_by_partial_link_text("Restore...").click()
tools_menu = self.driver.find_element_by_link_text(
NavMenuLocators.tools_menu_link_text)
tools_menu.click()
restore_obj = self.page.find_by_css_selector(
NavMenuLocators.restore_obj_css)
restore_obj.click()
self.wait.until(EC.visibility_of_element_located(
(By.NAME, NavMenuLocators.restore_file_name_txt_box_name)))
self.wait.until(EC.element_to_be_clickable(
(By.CSS_SELECTOR, ".file [name='file']")))
self.wait.until(EC.element_to_be_clickable(
(By.CSS_SELECTOR, ".file [name='file']"))).click()
(By.NAME, NavMenuLocators.restore_file_name_txt_box_name))).click()
self.page.fill_input_by_field_name(
"file", "test_backup", loose_focus=True)
NavMenuLocators.restore_file_name_txt_box_name,
"test_backup", loose_focus=True)
self.page.find_by_xpath("//button[contains(@class,'fa-upload')"
" and contains(.,'Restore')]").click()
restore_btn = self.page.find_by_xpath(
NavMenuLocators.restore_button_xpath)
restore_btn.click()
self.page.find_by_css_selector('.ajs-bg-bgprocess')
self.page.wait_for_element_to_disappear(
lambda driver: driver.find_element_by_css_selector(
NavMenuLocators.restore_file_name_txt_box_name))
# Wait for the backup status alertfier
self.wait.until(EC.visibility_of_element_located(
(By.CSS_SELECTOR,
NavMenuLocators.bcg_process_status_alertifier_css)))
status = test_utils.get_watcher_dialogue_status(self)
@@ -138,14 +184,18 @@ class PGUtilitiesBackupFeatureTest(BaseFeatureTest):
self.assertEquals(status, "Successfully completed.")
self.page.find_by_css_selector(
".pg-bg-more-details").click()
NavMenuLocators.status_alertifier_more_btn_css).click()
self.wait.until(EC.visibility_of_element_located(
(By.XPATH, NavMenuLocators.process_watcher_alertfier)))
# Check for XSS in Restore details
if self.is_xss_check:
self._check_detailed_window_for_xss('Restore')
else:
command = self.page.find_by_css_selector(
".bg-process-details .bg-detailed-desc").text
NavMenuLocators.process_watcher_detailed_command_canvas_css).\
text
self.assertIn(self.server['name'], str(command))
if os.name is not 'nt':
@@ -153,8 +203,9 @@ class PGUtilitiesBackupFeatureTest(BaseFeatureTest):
self.assertIn("pg_restore", str(command))
self.page.find_by_xpath("//div[contains(@class,'wcFloatingFocus')]"
"//div[contains(@class,'fa-close')]").click()
close_watcher = self.page.find_by_xpath(
NavMenuLocators.process_watcher_close_button_xpath)
close_watcher.click()
if backup_file is not None:
if os.path.isfile(backup_file):
@@ -175,7 +226,7 @@ class PGUtilitiesBackupFeatureTest(BaseFeatureTest):
def _check_detailed_window_for_xss(self, tool_name):
source_code = self.page.find_by_css_selector(
".bg-process-details .bg-detailed-desc"
NavMenuLocators.process_watcher_detailed_command_canvas_css
).get_attribute('innerHTML')
self._check_escaped_characters(
source_code,

View File

@@ -6,13 +6,15 @@
# This software is released under the PostgreSQL Licence
#
##########################################################################
import time
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By
from selenium.common.exceptions import ElementClickInterceptedException
from regression.feature_utils.base_feature_test import BaseFeatureTest
from regression.python_test_utils import test_utils
from regression.python_test_utils import test_gui_helper
from regression.feature_utils.locators import NavMenuLocators
import random
class PGUtilitiesMaintenanceFeatureTest(BaseFeatureTest):
@@ -55,6 +57,8 @@ class PGUtilitiesMaintenanceFeatureTest(BaseFeatureTest):
self.server['port'],
self.server['sslmode']
)
self.table_name = self.table_name + str(random.randint(1000, 3000))
test_utils.drop_database(connection, self.database_name)
test_utils.create_database(self.server, self.database_name)
test_utils.create_table(self.server, self.database_name,
@@ -66,8 +70,16 @@ class PGUtilitiesMaintenanceFeatureTest(BaseFeatureTest):
def runTest(self):
self._open_maintenance_dialogue()
self.page.click_modal('OK')
self.page.find_by_css_selector('.ajs-bg-bgprocess')
self._verify_command()
self.page.wait_for_element_to_disappear(
lambda driver: driver.find_element_by_xpath(
NavMenuLocators.maintenance_operation))
# Wait for the backup status alertfier
self.wait.until(EC.visibility_of_element_located(
(By.CSS_SELECTOR,
NavMenuLocators.bcg_process_status_alertifier_css)))
self.verify_command()
def _open_maintenance_dialogue(self):
self.page.toggle_open_server(self.server['name'])
@@ -78,30 +90,49 @@ class PGUtilitiesMaintenanceFeatureTest(BaseFeatureTest):
self.page.toggle_open_tree_item('public')
self.page.toggle_open_tables_node()
self.page.select_tree_item(self.table_name)
retry = 3
while retry > 0:
try:
tools_menu = self.driver.find_element_by_link_text(
NavMenuLocators.tools_menu_link_text)
tools_menu.click()
break
except ElementClickInterceptedException:
retry -= 1
maintenance_obj = self.wait.until(EC.visibility_of_element_located(
(By.CSS_SELECTOR, NavMenuLocators.maintenance_obj_css)))
maintenance_obj.click()
self.driver.find_element_by_link_text("Tools").click()
self.page.find_by_partial_link_text("Maintenance...").click()
time.sleep(0.5)
self.page.check_if_element_exist_by_xpath(
NavMenuLocators.maintenance_operation, 10)
def _verify_command(self):
def verify_command(self):
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()
self.page.find_by_css_selector(
NavMenuLocators.status_alertifier_more_btn_css).click()
self.wait.until(EC.visibility_of_element_located(
(By.XPATH, NavMenuLocators.process_watcher_alertfier)))
command = self.page.find_by_css_selector(
".bg-process-details .bg-detailed-desc").text
NavMenuLocators.
process_watcher_detailed_command_canvas_css).text
if self.test_level == 'database':
self.assertEquals(command, "VACUUM "
"(VERBOSE)\nRunning Query:"
self.assertEquals(command, "VACUUM (VERBOSE)\nRunning Query:"
"\nVACUUM VERBOSE;")
elif self.is_xss_check and self.test_level == 'table':
# Check for XSS in the dialog
source_code = self.page.find_by_css_selector(
".bg-process-details .bg-detailed-desc"
NavMenuLocators.
process_watcher_detailed_command_canvas_css
).get_attribute('innerHTML')
self._check_escaped_characters(
self.check_escaped_characters(
source_code,
'&lt;h1&gt;test_me&lt;/h1&gt;',
'Maintenance detailed window'
@@ -112,12 +143,14 @@ class PGUtilitiesMaintenanceFeatureTest(BaseFeatureTest):
"\nVACUUM VERBOSE"
" public." + self.table_name + ";")
self.page.find_by_css_selector(
"div.wcFloatingFocus div.fa-close").click()
self.page.find_by_xpath(
NavMenuLocators.process_watcher_close_button_xpath).click()
def after(self):
test_gui_helper.close_bgprocess_popup(self)
self.page.remove_server(self.server)
test_utils.delete_table(self.server, self.test_db,
self.table_name)
connection = test_utils.get_db_connection(
self.server['db'],
self.server['username'],
@@ -128,7 +161,7 @@ class PGUtilitiesMaintenanceFeatureTest(BaseFeatureTest):
)
test_utils.drop_database(connection, self.database_name)
def _check_escaped_characters(self, source_code, string_to_find, source):
def check_escaped_characters(self, source_code, string_to_find, source):
# 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)

View File

@@ -15,6 +15,7 @@ from selenium.webdriver import ActionChains
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 regression.feature_utils.locators import QueryToolLocators
class QueryToolAutoCompleteFeatureTest(BaseFeatureTest):
@@ -55,7 +56,10 @@ class QueryToolAutoCompleteFeatureTest(BaseFeatureTest):
test_utils.create_table(self.server, self.test_db,
self.second_table_name)
self._locate_database_tree_node()
self.page.toggle_open_tree_item(self.server['name'])
self.page.toggle_open_tree_item('Databases')
self.page.toggle_open_tree_item(self.test_db)
self.page.open_query_tool()
self.page.wait_for_spinner_to_disappear()
@@ -64,64 +68,64 @@ class QueryToolAutoCompleteFeatureTest(BaseFeatureTest):
print("\nAuto complete ALTER keyword... ", file=sys.stderr, end="")
self._auto_complete("A", "ALTER")
print("OK.", file=sys.stderr)
self._clear_query_tool()
self.page.clear_query_tool()
print("Auto complete BEGIN keyword... ", file=sys.stderr, end="")
self._auto_complete("BE", "BEGIN")
print("OK.", file=sys.stderr)
self._clear_query_tool()
self.page.clear_query_tool()
print("Auto complete CASCADED keyword... ", file=sys.stderr, end="")
self._auto_complete("CAS", "CASCADED")
print("OK.", file=sys.stderr)
self._clear_query_tool()
self.page.clear_query_tool()
print("Auto complete SELECT keyword... ", file=sys.stderr, end="")
self._auto_complete("SE", "SELECT")
print("OK.", file=sys.stderr)
self._clear_query_tool()
self.page.clear_query_tool()
print("Auto complete pg_backend_pid() function ... ",
file=sys.stderr, end="")
self._auto_complete("SELECT pg_", "pg_backend_pid()")
print("OK.", file=sys.stderr)
self._clear_query_tool()
self.page.clear_query_tool()
print("Auto complete current_query() function ... ",
file=sys.stderr, end="")
self._auto_complete("SELECT current_", "current_query()")
print("OK.", file=sys.stderr)
self._clear_query_tool()
self.page.clear_query_tool()
print("Auto complete function with argument ... ",
file=sys.stderr, end="")
self._auto_complete("SELECT pg_st", "pg_stat_file(filename)")
print("OK.", file=sys.stderr)
self._clear_query_tool()
self.page.clear_query_tool()
print("Auto complete schema other than default start with test_ ... ",
file=sys.stderr, end="")
self._auto_complete("SELECT * FROM te", self.first_schema_name)
print("OK.", file=sys.stderr)
self._clear_query_tool()
self.page.clear_query_tool()
print("Auto complete schema other than default starts with comp_ ... ",
file=sys.stderr, end="")
self._auto_complete("SELECT * FROM co", self.second_schema_name)
print("OK.", file=sys.stderr)
self._clear_query_tool()
self.page.clear_query_tool()
print("Auto complete first table in public schema ... ",
file=sys.stderr, end="")
self._auto_complete("SELECT * FROM public.", self.first_table_name)
print("OK.", file=sys.stderr)
self._clear_query_tool()
self.page.clear_query_tool()
print("Auto complete second table in public schema ... ",
file=sys.stderr, end="")
self._auto_complete("SELECT * FROM public.", self.second_table_name)
print("OK.", file=sys.stderr)
self._clear_query_tool()
self.page.clear_query_tool()
print("Auto complete JOIN second table with after schema name ... ",
file=sys.stderr, end="")
@@ -129,7 +133,7 @@ class QueryToolAutoCompleteFeatureTest(BaseFeatureTest):
" JOIN public."
self._auto_complete(query, self.second_table_name)
print("OK.", file=sys.stderr)
self._clear_query_tool()
self.page.clear_query_tool()
print("Auto complete JOIN ON some columns ... ",
file=sys.stderr, end="")
@@ -140,54 +144,51 @@ class QueryToolAutoCompleteFeatureTest(BaseFeatureTest):
".some_column"
self._auto_complete(query, expected_string)
print("OK.", file=sys.stderr)
self._clear_query_tool()
self.page.clear_query_tool()
print("Auto complete JOIN ON some columns using tabel alias ... ",
print("Auto complete JOIN ON some columns using table alias ... ",
file=sys.stderr, end="")
query = "SELECT * FROM public." + self.first_table_name + \
" t1 JOIN public." + self.second_table_name + " t2 ON t2."
self._auto_complete(query, "some_column = t1.some_column")
print("OK.", file=sys.stderr)
self._clear_query_tool()
self.page.clear_query_tool()
def after(self):
self.page.remove_server(self.server)
def _locate_database_tree_node(self):
self.page.toggle_open_tree_item(self.server['name'])
self.page.toggle_open_tree_item('Databases')
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']")
)
ActionChains(self.driver) \
.move_to_element(self.page.find_by_xpath("//*[@id='btn-clear']")) \
.perform()
self.page.click_element(
self.page.find_by_xpath("//*[@id='btn-clear']")
)
self.page.click_modal('Yes')
test_utils.delete_table(self.server, self.test_db,
self.first_table_name)
test_utils.delete_table(self.server, self.test_db,
self.second_table_name)
def _auto_complete(self, word, expected_string):
self.page.fill_codemirror_area_with(word)
ActionChains(self.page.driver).key_down(
Keys.CONTROL).send_keys(Keys.SPACE).key_up(Keys.CONTROL).perform()
# if IntelliSense is present then verify this
if self.page.check_if_element_exist_by_xpath(
"//ul[@class='CodeMirror-hints default']", 2):
hint_displayed = False
retry = 3
while retry > 0:
ActionChains(self.page.driver).key_down(
Keys.CONTROL).send_keys(Keys.SPACE).key_up(
Keys.CONTROL).perform()
if self.page.check_if_element_exist_by_xpath(
QueryToolLocators.code_mirror_hint_box_xpath, 20):
hint_displayed = True
break
else:
retry -= 1
if hint_displayed:
# if IntelliSense is present then verify this
self.page.find_by_xpath(
"//ul[contains(@class, 'CodeMirror-hints') and "
"contains(., '" + expected_string + "')]")
QueryToolLocators.code_mirror_hint_item_xpath.format(
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 expected_string not in code_mirror_text:
raise Exception("Required String %s is not "
"present" % expected_string)
code_mirror = self.driver.find_elements_by_xpath(
QueryToolLocators.code_mirror_data_xpath)
for data in code_mirror:
code_mirror_text = data.text
print("Single entry..........")
if expected_string not in code_mirror_text:
print("single entry exception.........")
raise Exception("Required String %s is not "
"present" % expected_string)

View File

@@ -14,10 +14,10 @@ import random
from selenium.webdriver import ActionChains
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.support.ui import WebDriverWait
from regression.python_test_utils import test_utils
from regression.feature_utils.base_feature_test import BaseFeatureTest
from .locators import QueryToolLocatorsCss
from regression.feature_utils.locators import QueryToolLocators
class QueryToolJourneyTest(BaseFeatureTest):
@@ -31,9 +31,12 @@ class QueryToolJourneyTest(BaseFeatureTest):
test_table_name = ""
test_editable_table_name = ""
invalid_table_name = ""
def before(self):
self.test_table_name = "test_table" + str(random.randint(1000, 3000))
self.invalid_table_name = \
"table_that_doesnt_exist_" + str(random.randint(1000, 3000))
test_utils.create_table(
self.server, self.test_db, self.test_table_name)
@@ -52,10 +55,11 @@ class QueryToolJourneyTest(BaseFeatureTest):
driver_version = test_utils.get_driver_version()
self.driver_version = float('.'.join(driver_version.split('.')[:2]))
self.wait = WebDriverWait(self.page.driver, 10)
def runTest(self):
self._navigate_to_query_tool()
self._execute_query(
self.page.execute_query(
"SELECT * FROM %s ORDER BY value " % self.test_table_name)
print("Copy rows...", file=sys.stderr, end="")
@@ -78,7 +82,7 @@ class QueryToolJourneyTest(BaseFeatureTest):
self._test_query_sources_and_generated_queries()
print(" OK.", file=sys.stderr)
print("Updatable resultsets...", file=sys.stderr, end="")
print("Updatable result sets...", file=sys.stderr, end="")
self._test_updatable_resultset()
print(" OK.", file=sys.stderr)
@@ -87,9 +91,14 @@ class QueryToolJourneyTest(BaseFeatureTest):
self.page.driver.switch_to.default_content()
self.page.driver.switch_to_frame(
self.page.driver.find_element_by_tag_name("iframe"))
self.page.find_by_xpath(
"//*[contains(@class, 'slick-row')]/*[1]").click()
self.page.find_by_xpath("//*[@id='btn-copy-row']").click()
select_row = self.page.find_by_xpath(
QueryToolLocators.output_row_xpath.format('1'))
select_row.click()
copy_row = self.page.find_by_css_selector(
QueryToolLocators.copy_button_css)
copy_row.click()
self.assertEqual('"Some-Name"\t"6"\t"some info"',
pyperclip.paste())
@@ -100,86 +109,85 @@ class QueryToolJourneyTest(BaseFeatureTest):
self.page.driver.switch_to.default_content()
self.page.driver.switch_to_frame(
self.page.driver.find_element_by_tag_name("iframe"))
self.page.find_by_xpath(
"//*[@data-test='output-column-header' and "
"contains(., 'some_column')]"
).click()
self.page.find_by_xpath("//*[@id='btn-copy-row']").click()
column_header = self.page.find_by_css_selector(
QueryToolLocators.output_column_header_css.format('some_column'))
column_header.click()
copy_btn = self.page.find_by_css_selector(
QueryToolLocators.copy_button_css)
copy_btn.click()
self.assertTrue('"Some-Name"' in pyperclip.paste())
self.assertTrue('"Some-Other-Name"' in pyperclip.paste())
self.assertTrue('"Yet-Another-Name"' in pyperclip.paste())
def _test_history_tab(self):
self.__clear_query_tool()
self.page.clear_query_tool()
editor_input = self.page.find_by_css_selector(
QueryToolLocatorsCss.query_editor_panel)
QueryToolLocators.query_editor_panel)
self.page.click_element(editor_input)
self._execute_query("SELECT * FROM table_that_doesnt_exist")
self.page.execute_query("SELECT * FROM %s" % self.invalid_table_name)
self.page.click_tab("Query History")
selected_history_entry = self.page.find_by_css_selector(
QueryToolLocatorsCss.query_history_selected)
self.assertIn("SELECT * FROM table_that_doesnt_exist",
QueryToolLocators.query_history_selected)
self.assertIn("SELECT * FROM %s" % self.invalid_table_name,
selected_history_entry.text)
failed_history_detail_pane = self.page.find_by_css_selector(
QueryToolLocatorsCss.query_history_detail)
QueryToolLocators.query_history_detail)
self.assertIn(
"Error Message relation \"table_that_doesnt_exist\" "
"does not exist", failed_history_detail_pane.text
"Error Message relation \"%s\" does not exist"
% self.invalid_table_name,
failed_history_detail_pane.text
)
self.page.wait_for_element(lambda driver: driver
.find_element_by_css_selector(
"#query_list> .query-group>ul>li"))
self.page.wait_for_elements(
lambda driver: driver.find_elements_by_css_selector(
QueryToolLocators.query_history_entries))
# 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")
QueryToolLocators.query_history_entries)
history_rows[1].click()
selected_history_entry = self.page.find_by_css_selector(
"#query_list .selected")
QueryToolLocators.query_history_selected)
self.assertIn(("SELECT * FROM %s ORDER BY value" %
self.test_table_name),
selected_history_entry.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']/div/ul/li[1]")
newly_selected_history_entry = history_rows[0]
self.page.click_element(newly_selected_history_entry)
selected_invalid_history_entry = self.page.find_by_css_selector(
"#query_list .selected .entry.error .query")
invalid_history_entry = self.page.find_by_css_selector(
QueryToolLocators.invalid_query_history_entry_css)
self.assertIn("SELECT * FROM table_that_doesnt_exist",
selected_invalid_history_entry.text)
self.assertIn("SELECT * FROM %s" % self.invalid_table_name,
invalid_history_entry.text)
self.page.click_tab("Query Editor")
self.__clear_query_tool()
self.page.clear_query_tool()
self.page.click_element(editor_input)
# Check if 15 more query executed then the history should contain 17
# entries.
self.page.fill_codemirror_area_with("SELECT * FROM hats")
for _ in range(15):
self.page.find_by_css_selector(
QueryToolLocatorsCss.btn_execute_query).click()
QueryToolLocators.btn_execute_query_css).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']/div/ul/li[17]")
query_list = self.page.wait_for_elements(
lambda driver: driver.find_elements_by_css_selector(
QueryToolLocators.query_history_entries))
self.page.click_element(query_we_need_to_scroll_to)
for _ in range(17):
ActionChains(self.page.driver) \
.send_keys(Keys.ARROW_DOWN) \
.perform()
self._assert_clickable(query_we_need_to_scroll_to)
self.assertTrue(17, len(query_list))
def _test_query_sources_and_generated_queries(self):
self.__clear_query_history()
@@ -193,12 +201,12 @@ class QueryToolJourneyTest(BaseFeatureTest):
self.page.click_tab("Query History")
history_entries_icons = [
QueryToolLocatorsCss.commit_icon,
QueryToolLocatorsCss.save_data_icon,
QueryToolLocatorsCss.save_data_icon,
QueryToolLocatorsCss.execute_icon,
QueryToolLocatorsCss.explain_analyze_icon,
QueryToolLocatorsCss.explain_icon
QueryToolLocators.commit_icon,
QueryToolLocators.save_data_icon,
QueryToolLocators.save_data_icon,
QueryToolLocators.execute_icon,
QueryToolLocators.explain_analyze_icon,
QueryToolLocators.explain_icon
]
history_entries_queries = [
@@ -217,33 +225,31 @@ class QueryToolJourneyTest(BaseFeatureTest):
def _test_toggle_generated_queries(self):
xpath = '//li[contains(@class, "pgadmin-query-history-entry")]'
self.assertTrue(self.page.check_if_element_exist_by_xpath(xpath))
toggle_el = self.page.find_by_xpath(
'//input[@id ="generated-queries-toggle"]/..'
)
toggle_el.click()
self.page.set_switch_box_status(
QueryToolLocators.show_query_internally_btn, 'No')
self.assertFalse(self.page.check_if_element_exist_by_xpath(xpath))
toggle_el.click()
self.page.set_switch_box_status(
QueryToolLocators.show_query_internally_btn, 'Yes')
self.assertTrue(self.page.check_if_element_exist_by_xpath(xpath))
def _test_updatable_resultset(self):
if self.driver_version < 2.8:
return
self.page.click_tab("Query Editor")
# Select all data (contains the primary key -> should be editable)
self.__clear_query_tool()
self.page.clear_query_tool()
query = "SELECT pk_column, normal_column FROM %s" \
% self.test_editable_table_name
self._check_query_results_editable(query, True)
# Select data without primary keys -> should not be editable
self.__clear_query_tool()
self.page.clear_query_tool()
query = "SELECT normal_column FROM %s" % self.test_editable_table_name
self._check_query_results_editable(query, False)
def _execute_sources_test_queries(self):
self.__clear_query_tool()
self.page.clear_query_tool()
self._explain_query(
"SELECT * FROM %s;"
@@ -253,17 +259,17 @@ class QueryToolJourneyTest(BaseFeatureTest):
"SELECT * FROM %s;"
% self.test_editable_table_name
)
self._execute_query(
self.page.execute_query(
"SELECT * FROM %s;"
% self.test_editable_table_name
)
# Turn off autocommit
query_options = self.page.find_by_css_selector(
QueryToolLocatorsCss.btn_query_dropdown)
QueryToolLocators.btn_query_dropdown)
query_options.click()
self.page.find_by_css_selector(
QueryToolLocatorsCss.btn_auto_commit).click()
QueryToolLocators.btn_auto_commit).click()
query_options.click() # Click again to close dropdown
self._update_numeric_cell(2, 10)
@@ -272,24 +278,25 @@ class QueryToolJourneyTest(BaseFeatureTest):
# Turn on autocommit
query_options = self.page.find_by_css_selector(
QueryToolLocatorsCss.btn_query_dropdown)
QueryToolLocators.btn_query_dropdown)
query_options.click()
self.page.find_by_css_selector(
QueryToolLocatorsCss.btn_auto_commit).click()
QueryToolLocators.btn_auto_commit).click()
query_options.click() # Click again to close dropdown
def _check_history_queries_and_icons(self, history_queries, history_icons):
# Select first query history entry
self.page.find_by_xpath("//*[@id='query_list']/div/ul/li[1]").click()
self.page.find_by_css_selector(
QueryToolLocators.query_history_specific_entry.format(1)).click()
for icon, query in zip(history_icons, history_queries):
# Check query
query_history_selected_item = self.page.find_by_css_selector(
QueryToolLocatorsCss.query_history_selected
QueryToolLocators.query_history_selected
)
self.assertIn(query, query_history_selected_item.text)
# Check source icon
query_history_selected_icon = self.page.find_by_css_selector(
QueryToolLocatorsCss.query_history_selected_icon)
QueryToolLocators.query_history_selected_icon)
icon_classes = query_history_selected_icon.get_attribute('class')
icon_classes = icon_classes.split(" ")
self.assertTrue(icon in icon_classes)
@@ -302,47 +309,37 @@ class QueryToolJourneyTest(BaseFeatureTest):
"""
Updates a numeric cell in the first row of the resultset
"""
xpath = '//div[contains(@class, "slick-row") and ' \
'contains(@style, "top:0px")]'
xpath += '/div[contains(@class, "slick-cell") and ' \
'contains(@class, "r' + str(cell_index) + '")]'
cell_el = self.page.find_by_xpath(xpath)
self.page.check_if_element_exist_by_xpath(
"//div[contains(@style, 'top:0px')]//div[contains(@class, "
"'l{0} r{1}')]".format(cell_index, cell_index))
cell_el = self.page.find_by_xpath(
"//div[contains(@style, 'top:0px')]//div[contains(@class, "
"'l{0} r{1}')]".format(cell_index, cell_index))
ActionChains(self.driver).double_click(cell_el).perform()
ActionChains(self.driver).send_keys(value). \
send_keys(Keys.ENTER).perform()
self.page.find_by_css_selector(
QueryToolLocatorsCss.btn_save_data).click()
QueryToolLocators.btn_save_data).click()
def _insert_data_into_test_editable_table(self):
self.page.click_tab("Query Editor")
self.__clear_query_tool()
self._execute_query(
self.page.clear_query_tool()
self.page.execute_query(
"INSERT INTO %s VALUES (1, 1), (2, 2);"
% self.test_editable_table_name
)
def __clear_query_tool(self):
self.page.click_element(
self.page.find_by_xpath("//*[@id='btn-clear-dropdown']")
)
ActionChains(self.driver)\
.move_to_element(self.page.find_by_xpath("//*[@id='btn-clear']"))\
.perform()
self.page.click_element(
self.page.find_by_xpath("//*[@id='btn-clear']")
)
self.page.click_modal('Yes')
def __clear_query_history(self):
self.page.click_element(
self.page.find_by_xpath("//*[@id='btn-clear-dropdown']")
self.page.find_by_css_selector(
QueryToolLocators.btn_clear_dropdown)
)
ActionChains(self.driver)\
.move_to_element(
self.page.find_by_xpath(
"//*[@id='btn-clear-history']")).perform()
self.page.find_by_css_selector(
QueryToolLocators.btn_clear_history)).perform()
self.page.click_element(
self.page.find_by_xpath("//*[@id='btn-clear-history']")
self.page.find_by_css_selector(QueryToolLocators.btn_clear_history)
)
self.page.click_modal('Yes')
@@ -353,44 +350,39 @@ class QueryToolJourneyTest(BaseFeatureTest):
self.page.open_query_tool()
self.page.wait_for_spinner_to_disappear()
def _execute_query(self, query):
self.page.fill_codemirror_area_with(query)
self.page.find_by_css_selector(
QueryToolLocatorsCss.btn_execute_query).click()
def _explain_query(self, query):
self.page.fill_codemirror_area_with(query)
self.page.find_by_css_selector(
QueryToolLocatorsCss.btn_explain).click()
QueryToolLocators.btn_explain).click()
def _explain_analyze_query(self, query):
self.page.fill_codemirror_area_with(query)
self.page.find_by_css_selector(
QueryToolLocatorsCss.btn_explain_analyze).click()
QueryToolLocators.btn_explain_analyze).click()
def _commit_transaction(self):
self.page.find_by_css_selector(
QueryToolLocatorsCss.btn_commit).click()
QueryToolLocators.btn_commit).click()
def _assert_clickable(self, element):
self.page.click_element(element)
def _check_query_results_editable(self, query, should_be_editable):
self._execute_query(query)
self.page.wait_for_spinner_to_disappear()
self.page.execute_query(query)
# Check if the first cell in the first row is editable
is_editable = self._check_cell_editable(1)
self.assertEqual(is_editable, should_be_editable)
def _check_cell_editable(self, cell_index):
"""
Checks if a cell in the first row of the resultset is editable
"""
xpath = '//div[contains(@class, "slick-row") and ' \
'contains(@style, "top:0px")]'
xpath += '/div[contains(@class, "slick-cell") and ' \
'contains(@class, "r' + str(cell_index) + '")]'
cell_el = self.page.find_by_xpath(xpath)
"""Checks if a cell in the first row of the resultset is editable"""
self.page.check_if_element_exist_by_xpath(
"//div[contains(@style, 'top:0px')]//div[contains(@class, "
"'l{0} r{1}')]".format(cell_index, cell_index))
cell_el = self.page.find_by_xpath(
"//div[contains(@style, 'top:0px')]//div[contains(@class, "
"'l{0} r{1}')]".format(cell_index, cell_index))
# Get existing value
cell_value = int(cell_el.text)
new_value = cell_value + 1
@@ -401,6 +393,12 @@ class QueryToolJourneyTest(BaseFeatureTest):
# Check if the value was updated
return int(cell_el.text) == new_value
def _check_can_add_row(self):
return self.page.check_if_element_exist_by_xpath(
QueryToolLocators.new_row_xpath)
def after(self):
self.page.close_query_tool()
self.page.remove_server(self.server)
test_utils.delete_table(
self.server, self.test_db, self.test_table_name)

View File

@@ -10,15 +10,16 @@
from __future__ import print_function
import sys
from selenium.common.exceptions import StaleElementReferenceException
from selenium.webdriver import ActionChains
from selenium.common.exceptions import StaleElementReferenceException, \
ElementClickInterceptedException
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
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
from regression.feature_utils.locators import \
QueryToolLocators
class QueryToolFeatureTest(BaseFeatureTest):
@@ -33,17 +34,20 @@ class QueryToolFeatureTest(BaseFeatureTest):
def before(self):
self.page.wait_for_spinner_to_disappear()
self.page.add_server(self.server)
self._locate_database_tree_node()
self.page.toggle_open_tree_item(self.server['name'])
self.page.toggle_open_tree_item('Databases')
self.page.toggle_open_tree_item(self.test_db)
self.page.open_query_tool()
self.page.wait_for_spinner_to_disappear()
self._reset_options()
self.wait = WebDriverWait(self.page.driver, 10)
def runTest(self):
# on demand result set on scrolling.
print("\nOn demand query result... ",
file=sys.stderr, end="")
self._on_demand_result()
self._clear_query_tool()
self.page.clear_query_tool()
# explain query with verbose and cost
print("Explain query with verbose and cost... ",
@@ -51,7 +55,7 @@ class QueryToolFeatureTest(BaseFeatureTest):
if self._supported_server_version():
self._query_tool_explain_with_verbose_and_cost()
print("OK.", file=sys.stderr)
self._clear_query_tool()
self.page.clear_query_tool()
else:
print("Skipped.", file=sys.stderr)
@@ -61,7 +65,7 @@ class QueryToolFeatureTest(BaseFeatureTest):
if self._supported_server_version():
self._query_tool_explain_analyze_with_buffers_and_timing()
print("OK.", file=sys.stderr)
self._clear_query_tool()
self.page.clear_query_tool()
else:
print("Skipped.", file=sys.stderr)
@@ -69,30 +73,30 @@ class QueryToolFeatureTest(BaseFeatureTest):
print("Auto commit disabled... ", file=sys.stderr, end="")
self._query_tool_auto_commit_disabled()
print("OK.", file=sys.stderr)
self._clear_query_tool()
self.page.clear_query_tool()
# auto commit enabled.
print("Auto commit enabled... ", file=sys.stderr, end="")
self._query_tool_auto_commit_enabled()
print("OK.", file=sys.stderr)
self._clear_query_tool()
self.page.clear_query_tool()
# auto rollback enabled.
print("Auto rollback enabled...", file=sys.stderr, end="")
self._query_tool_auto_rollback_enabled()
print(" OK.", file=sys.stderr)
self._clear_query_tool()
self.page.clear_query_tool()
# cancel query.
print("Cancel query... ", file=sys.stderr, end="")
self._query_tool_cancel_query()
print("OK.", file=sys.stderr)
self._clear_query_tool()
self.page.clear_query_tool()
# Notify Statements.
print("Capture Notify Statements... ", file=sys.stderr, end="")
self._query_tool_notify_statements()
self._clear_query_tool()
self.page.clear_query_tool()
# explain query with JIT stats
print("Explain query with JIT stats... ",
@@ -100,7 +104,7 @@ class QueryToolFeatureTest(BaseFeatureTest):
if self._supported_jit_on_server():
self._query_tool_explain_check_jit_stats()
print("OK.", file=sys.stderr)
self._clear_query_tool()
self.page.clear_query_tool()
else:
print("Skipped.", file=sys.stderr)
@@ -112,33 +116,33 @@ class QueryToolFeatureTest(BaseFeatureTest):
self.page.fill_codemirror_area_with('')
explain_op = self.page.find_by_css_selector(
QueryToolLocatorsCss.btn_explain_options_dropdown)
QueryToolLocators.btn_explain_options_dropdown)
explain_op.click()
# disable Explain options and auto rollback only if they are enabled.
for op in (QueryToolLocatorsCss.btn_explain_verbose,
QueryToolLocatorsCss.btn_explain_costs,
QueryToolLocatorsCss.btn_explain_buffers,
QueryToolLocatorsCss.btn_explain_timing):
for op in (QueryToolLocators.btn_explain_verbose,
QueryToolLocators.btn_explain_costs,
QueryToolLocators.btn_explain_buffers,
QueryToolLocators.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_css_selector(
QueryToolLocatorsCss.btn_query_dropdown)
QueryToolLocators.btn_query_dropdown)
query_op.click()
# disable auto rollback only if they are enabled
btn = self.page.find_by_css_selector(
QueryToolLocatorsCss.btn_auto_rollback)
QueryToolLocators.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_css_selector(
QueryToolLocatorsCss.btn_auto_commit)
QueryToolLocators.btn_auto_commit)
check = btn.find_element_by_tag_name('i')
if 'visibility-hidden' in check.get_attribute('class'):
btn.click()
@@ -146,23 +150,6 @@ class QueryToolFeatureTest(BaseFeatureTest):
# close menu
query_op.click()
def _locate_database_tree_node(self):
self.page.toggle_open_tree_item(self.server['name'])
self.page.toggle_open_tree_item('Databases')
self.page.toggle_open_tree_item(self.test_db)
def _clear_query_tool(self):
self.page.click_element(self.page.find_by_css_selector(
QueryToolLocatorsCss.btn_clear_dropdown)
)
ActionChains(self.driver) \
.move_to_element(self.page.find_by_css_selector(
QueryToolLocatorsCss.btn_clear)).perform()
self.page.click_element(
self.page.find_by_css_selector(QueryToolLocatorsCss.btn_clear)
)
self.page.click_modal('Yes')
def _on_demand_result(self):
ON_DEMAND_CHUNKS = 2
row_id_to_find = config.ON_DEMAND_RECORD_COUNT * ON_DEMAND_CHUNKS
@@ -175,126 +162,133 @@ SELECT generate_series(1, {}) as id1, 'dummy' as id2""".format(
print("\nOn demand result set on scrolling... ",
file=sys.stderr, end="")
wait = WebDriverWait(self.page.driver, 10)
self.page.fill_codemirror_area_with(query)
self.page.find_by_css_selector(
QueryToolLocatorsCss.btn_execute_query).click()
self.page.execute_query(query)
# wait for header of the table to be visible
wait.until(EC.visibility_of_element_located(
(By.XPATH, '//div[@class="slick-header-columns"]')))
self.wait.until(EC.visibility_of_element_located(
(By.CSS_SELECTOR, QueryToolLocators.query_output_canvas_css)))
wait.until(EC.presence_of_element_located(
(By.XPATH,
'//span[@data-row="0" and text()="1"]'))
)
self.wait.until(EC.presence_of_element_located(
(By.CSS_SELECTOR,
QueryToolLocators.query_output_cells)))
# scroll to bottom to fetch next chunk of result set.
self.driver.execute_script(
"pgAdmin.SqlEditor.jquery('.slick-viewport')"
".scrollTop(pgAdmin.SqlEditor.jquery('.grid-canvas').height());"
)
canvas = self.page.find_by_css_selector(
QueryToolLocators.query_output_canvas_css)
canvas = wait.until(EC.presence_of_element_located(
(By.CSS_SELECTOR, "#datagrid .slick-viewport .grid-canvas")))
self._check_ondemand_result(row_id_to_find, canvas)
self._check_ondemand_result(row_id_to_find)
print("OK.", file=sys.stderr)
print("On demand result set on grid select all... ",
file=sys.stderr, end="")
self.page.find_by_css_selector(
QueryToolLocatorsCss.btn_execute_query).click()
QueryToolLocators.btn_execute_query_css).click()
# wait for header of the table to be visible
wait.until(EC.visibility_of_element_located(
(By.XPATH, '//div[@class="slick-header-columns"]')))
canvas = self.page.find_by_css_selector(
QueryToolLocators.query_output_canvas_css)
# wait for first row to contain value
wait.until(EC.presence_of_element_located(
(By.XPATH,
'//span[@data-row="0" and text()="1"]'))
# wait for the rows in the table to be displayed
self.wait.until(EC.presence_of_element_located(
(By.CSS_SELECTOR,
QueryToolLocators.query_output_cells))
)
wait.until(EC.presence_of_element_located(
(By.CSS_SELECTOR, ".slick-header-column"))).click()
# Select all rows in a table
multiple_check = True
count = 0
while multiple_check:
try:
select_all = self.wait.until(EC.element_to_be_clickable(
(By.XPATH, QueryToolLocators.select_all_column)))
select_all.click()
multiple_check = False
except (StaleElementReferenceException,
ElementClickInterceptedException):
count += 1
pass
print(count)
canvas = wait.until(EC.presence_of_element_located(
(By.CSS_SELECTOR, "#datagrid .slick-viewport .grid-canvas")))
self._check_ondemand_result(row_id_to_find, canvas)
self._check_ondemand_result(row_id_to_find)
print("OK.", file=sys.stderr)
print("On demand result set on column select all... ",
file=sys.stderr, end="")
self.page.find_by_css_selector(
QueryToolLocatorsCss.btn_execute_query).click()
QueryToolLocators.btn_execute_query_css).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"]')))
self.wait.until(EC.visibility_of_element_located(
(By.CSS_SELECTOR, QueryToolLocators.query_output_canvas_css)))
wait.until(EC.presence_of_element_located(
(By.XPATH,
'//span[@data-row="0" and text()="1"]'))
# wait for the rows in the table to be displayed
self.wait.until(EC.presence_of_element_located(
(By.CSS_SELECTOR,
QueryToolLocators.query_output_cells))
)
# click on first data column to select all column.
wait.until(EC.presence_of_element_located(
(
By.XPATH,
"//span[contains(@class, 'column-name') "
"and contains(., 'id1')]"))
).click()
column_1 = \
self.page.find_by_css_selector(
QueryToolLocators.output_column_header_css.format('id1'))
column_1.click()
canvas = wait.until(EC.presence_of_element_located(
(By.CSS_SELECTOR, "#datagrid .slick-viewport .grid-canvas")))
canvas = self.wait.until(EC.presence_of_element_located(
(By.CSS_SELECTOR, QueryToolLocators.query_output_canvas_css)))
self._check_ondemand_result(row_id_to_find, canvas)
self._check_ondemand_result(row_id_to_find)
print("OK.", file=sys.stderr)
def _check_ondemand_result(self, row_id_to_find, canvas):
def _check_ondemand_result(self, row_id_to_find):
# scroll to bottom to bring last row of next chunk in viewport.
self.driver.execute_script(
"pgAdmin.SqlEditor.jquery('.slick-viewport')"
".scrollTop(pgAdmin.SqlEditor.jquery('.grid-canvas').height());"
)
# canvas_ele = self.page.find_by_css_selector()
scroll = 10
while scroll:
canvas_ele = self.page.find_by_css_selector('.grid-canvas')
scrolling_height = canvas_ele.size['height']
self.driver.execute_script(
"pgAdmin.SqlEditor.jquery('.slick-viewport')"
".scrollTop(pgAdmin.SqlEditor.jquery('.grid-canvas')"
".height());"
)
import time
time.sleep(0.5)
if canvas_ele.size['height'] == scrolling_height:
break
else:
scroll -= 1
canvas.find_element_by_xpath(
'//span[text()="{}"]'.format(row_id_to_find)
)
self.assertTrue(self.page.check_if_element_exist_by_xpath(
QueryToolLocators.output_column_data_xpath.format(row_id_to_find)
))
def _query_tool_explain_with_verbose_and_cost(self):
query = """-- Explain query with verbose and cost
SELECT generate_series(1, 1000) as id order by id desc"""
wait = WebDriverWait(self.page.driver, 10)
self.page.fill_codemirror_area_with(query)
explain_op = self.page.find_by_css_selector(
QueryToolLocatorsCss.btn_explain_options_dropdown)
QueryToolLocators.btn_explain_options_dropdown)
explain_op.click()
# disable Explain options and auto rollback only if they are enabled.
for op in (QueryToolLocatorsCss.btn_explain_verbose,
QueryToolLocatorsCss.btn_explain_costs):
for op in (QueryToolLocators.btn_explain_verbose,
QueryToolLocators.btn_explain_costs):
self.page.find_by_css_selector(op).click()
explain_op.click()
self.page.find_by_css_selector(
QueryToolLocatorsCss.btn_explain).click()
QueryToolLocators.btn_explain).click()
self.page.wait_for_query_tool_loading_indicator_to_disappear()
self.page.click_tab('Data Output')
canvas = wait.until(EC.presence_of_element_located(
(By.CSS_SELECTOR, "#datagrid .slick-viewport .grid-canvas"))
canvas = self.wait.until(EC.presence_of_element_located(
(By.CSS_SELECTOR, QueryToolLocators.query_output_canvas_css))
)
# Search for 'Output' word in result (verbose option)
@@ -307,40 +301,38 @@ SELECT generate_series(1, 1000) as id order by id desc"""
query = """-- Explain analyze query with buffers and timing
SELECT generate_series(1, 1000) as id order by id desc"""
wait = WebDriverWait(self.page.driver, 10)
self.page.fill_codemirror_area_with(query)
explain_op = self.page.find_by_css_selector(
QueryToolLocatorsCss.btn_explain_options_dropdown)
QueryToolLocators.btn_explain_options_dropdown)
explain_op.click()
# disable Explain options and auto rollback only if they are enabled.
for op in (QueryToolLocatorsCss.btn_explain_buffers,
QueryToolLocatorsCss.btn_explain_timing):
for op in (QueryToolLocators.btn_explain_buffers,
QueryToolLocators.btn_explain_timing):
self.page.find_by_css_selector(op).click()
explain_op.click()
self.page.find_by_css_selector(
QueryToolLocatorsCss.btn_explain_analyze).click()
QueryToolLocators.btn_explain_analyze).click()
self.page.wait_for_query_tool_loading_indicator_to_disappear()
self.page.click_tab('Data Output')
canvas = wait.until(EC.presence_of_element_located(
(By.CSS_SELECTOR, "#datagrid .slick-viewport .grid-canvas"))
)
# Search for 'Shared Read Blocks' word in result (buffers option)
canvas.find_element_by_xpath(
"//*[contains(string(), 'Shared Read Blocks')]"
self.wait.until(EC.presence_of_element_located(
(By.XPATH, QueryToolLocators.output_cell_xpath.format(1, 1)))
)
result = self.page.find_by_xpath(
QueryToolLocators.output_cell_xpath.format(1, 1))
# Search for 'Shared Read Blocks' word in result (buffers option)
self.assertIn('Shared Read Blocks', result.text)
# Search for 'Actual Total Time' word in result (timing option)
canvas.find_element_by_xpath(
"//*[contains(string(), 'Actual Total Time')]"
)
self.assertIn('Actual Total Time', result.text)
def _query_tool_auto_commit_disabled(self):
table_name = 'query_tool_auto_commit_disabled_table'
@@ -349,32 +341,31 @@ SELECT generate_series(1, 1000) as id order by id desc"""
-- 3. ROLLBACK transaction.
-- 4. Check if table is *NOT* created.
CREATE TABLE public.{}();""".format(table_name)
wait = WebDriverWait(self.page.driver, 10)
self.page.fill_codemirror_area_with(query)
# open auto commit option and disable it
query_op = self.page.find_by_css_selector(
QueryToolLocatorsCss.btn_query_dropdown)
QueryToolLocators.btn_query_dropdown)
query_op.click()
self.page.find_by_css_selector(
QueryToolLocatorsCss.btn_auto_commit).click()
QueryToolLocators.btn_auto_commit).click()
# close option
query_op.click()
# execute query
self.page.find_by_css_selector(
QueryToolLocatorsCss.btn_execute_query).click()
QueryToolLocators.btn_execute_query_css).click()
self.page.wait_for_query_tool_loading_indicator_to_disappear()
self.page.click_tab('Messages')
self.page.find_by_xpath(
'//div[contains(@class, "sql-editor-message") and '
'contains(string(), "CREATE TABLE")]'
)
self.assertTrue(self.page.check_if_element_exist_by_xpath(
QueryToolLocators.sql_editor_message.format('CREATE TABLE')),
"CREATE TABLE message does not displayed")
# do the ROLLBACK and check if the table is present or not
self._clear_query_tool()
self.page.clear_query_tool()
query = """-- 1. (Done) Disable auto commit.
-- 2. (Done) Create table in public schema.
-- 3. ROLLBACK transaction.
@@ -382,16 +373,15 @@ CREATE TABLE public.{}();""".format(table_name)
ROLLBACK;"""
self.page.fill_codemirror_area_with(query)
self.page.find_by_css_selector(
QueryToolLocatorsCss.btn_execute_query).click()
QueryToolLocators.btn_execute_query_css).click()
self.page.wait_for_query_tool_loading_indicator_to_disappear()
self.page.click_tab('Messages')
self.page.find_by_xpath(
'//div[contains(@class, "sql-editor-message") and '
'contains(string(), "ROLLBACK")]'
)
self.assertTrue(self.page.check_if_element_exist_by_xpath(
QueryToolLocators.sql_editor_message.format('ROLLBACK')),
"ROLLBACK message does not displayed")
self._clear_query_tool()
self.page.clear_query_tool()
query = """-- 1. (Done) Disable auto commit.
-- 2. (Done) Create table in public schema.
-- 3. (Done) ROLLBACK transaction.
@@ -400,16 +390,15 @@ 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_css_selector(
QueryToolLocatorsCss.btn_execute_query).click()
QueryToolLocators.btn_execute_query_css).click()
self.page.wait_for_query_tool_loading_indicator_to_disappear()
self.page.click_tab('Data Output')
canvas = wait.until(EC.presence_of_element_located(
(By.CSS_SELECTOR, "#datagrid .slick-viewport .grid-canvas")))
canvas = self.wait.until(EC.presence_of_element_located(
(By.CSS_SELECTOR, QueryToolLocators.query_output_canvas_css)))
el = canvas.find_elements_by_xpath(
"//div[contains(@class, 'slick-cell') and "
"contains(text(), '{}')]".format(table_name))
QueryToolLocators.output_column_data_xpath.format(table_name))
assert len(el) == 0, "Table '{}' created with auto commit disabled " \
"and without any explicit commit.".format(
@@ -423,7 +412,7 @@ SELECT relname FROM pg_class
ROLLBACK;"""
self.page.fill_codemirror_area_with(query)
self.page.find_by_css_selector(
QueryToolLocatorsCss.btn_execute_query).click()
QueryToolLocators.btn_execute_query_css).click()
self.page.wait_for_query_tool_loading_indicator_to_disappear()
@@ -437,23 +426,21 @@ END;"""
self.page.fill_codemirror_area_with(query)
wait = WebDriverWait(self.page.driver, 10)
query_op = self.page.find_by_css_selector(
QueryToolLocatorsCss.btn_query_dropdown)
QueryToolLocators.btn_query_dropdown)
query_op.click()
self.page.find_by_css_selector(
QueryToolLocatorsCss.btn_auto_commit).click()
QueryToolLocators.btn_auto_commit).click()
query_op.click()
self.page.find_by_css_selector(
QueryToolLocatorsCss.btn_execute_query).click()
QueryToolLocators.btn_execute_query_css).click()
self.page.wait_for_query_tool_loading_indicator_to_disappear()
self._clear_query_tool()
self.page.clear_query_tool()
table_name = 'query_tool_auto_commit_enabled_table'
query = """-- 1. (Done) END any open transaction.
@@ -463,37 +450,29 @@ END;"""
-- 5. Check if table is created event after ROLLBACK.
CREATE TABLE public.{}();""".format(table_name)
self.page.fill_codemirror_area_with(query)
self.page.find_by_css_selector(
QueryToolLocatorsCss.btn_execute_query).click()
self.page.execute_query(query)
self.page.wait_for_query_tool_loading_indicator_to_disappear()
self.page.click_tab('Messages')
self.page.find_by_xpath(
'//div[contains(@class, "sql-editor-message") and '
'contains(string(), "CREATE TABLE")]'
)
self.assertTrue(self.page.check_if_element_exist_by_xpath(
QueryToolLocators.sql_editor_message.format('CREATE TABLE')),
"CREATE TABLE message does not displayed")
self._clear_query_tool()
self.page.clear_query_tool()
query = """-- 1. (Done) END any open transaction if any.
-- 2. (Done) Enable auto commit.
-- 3. (Done) Create table in public schema.
-- 4. ROLLBACK transaction
-- 5. Check if table is created event after ROLLBACK.
ROLLBACK;"""
self.page.fill_codemirror_area_with(query)
self.page.find_by_css_selector(
QueryToolLocatorsCss.btn_execute_query).click()
self.page.execute_query(query)
self.page.wait_for_query_tool_loading_indicator_to_disappear()
self.page.click_tab('Messages')
self.page.find_by_xpath(
'//div[contains(@class, "sql-editor-message") and '
'contains(string(), "ROLLBACK")]'
)
self.assertTrue(self.page.check_if_element_exist_by_xpath(
QueryToolLocators.sql_editor_message.format('ROLLBACK')),
"ROLLBACK message does not displayed")
self._clear_query_tool()
self.page.clear_query_tool()
query = """-- 1. (Done) END any open transaction if any.
-- 2. (Done) Enable auto commit.
-- 3. (Done) Create table in public schema.
@@ -503,17 +482,16 @@ 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_css_selector(
QueryToolLocatorsCss.btn_execute_query).click()
QueryToolLocators.btn_execute_query_css).click()
self.page.click_tab('Data Output')
self.page.wait_for_query_tool_loading_indicator_to_disappear()
canvas = wait.until(EC.presence_of_element_located(
(By.CSS_SELECTOR, "#datagrid .slick-viewport .grid-canvas")))
canvas = self.wait.until(EC.presence_of_element_located(
(By.CSS_SELECTOR, QueryToolLocators.query_output_canvas_css)))
el = canvas.find_elements_by_xpath(
"//div[contains(@class, 'slick-cell') and "
"contains(text(), '{}')]".format(table_name))
QueryToolLocators.output_column_data_xpath.format(table_name))
assert len(el) != 0, "Table '{}' is not created with auto " \
"commit enabled.".format(table_name)
@@ -527,12 +505,11 @@ SELECT relname FROM pg_class
-- 5. END transaction.
-- 6. Check if table is *NOT* created after ending transaction.
END;"""
wait = WebDriverWait(self.page.driver, 10)
self.page.fill_codemirror_area_with(query)
query_op = self.page.find_by_css_selector(
QueryToolLocatorsCss.btn_query_dropdown)
QueryToolLocators.btn_query_dropdown)
query_op.click()
# uncheckt auto commit and check auto-rollback
@@ -542,10 +519,10 @@ END;"""
query_op.click()
self.page.find_by_css_selector(
QueryToolLocatorsCss.btn_execute_query).click()
QueryToolLocators.btn_execute_query_css).click()
self.page.wait_for_query_tool_loading_indicator_to_disappear()
self._clear_query_tool()
self.page.clear_query_tool()
query = """-- 1. (Done) END any open transaction.
-- 2. Enable auto rollback and disable auto commit.
@@ -554,21 +531,14 @@ END;"""
-- 5. END transaction.
-- 6. Check if table is *NOT* created after ending transaction.
CREATE TABLE public.{}();""".format(table_name)
wait = WebDriverWait(self.page.driver, 10)
self.page.fill_codemirror_area_with(query)
self.page.find_by_css_selector(
QueryToolLocatorsCss.btn_execute_query).click()
self.page.execute_query(query)
self.page.wait_for_query_tool_loading_indicator_to_disappear()
self.page.click_tab('Messages')
self.page.find_by_xpath(
'//div[contains(@class, "sql-editor-message") and '
'contains(string(), "CREATE TABLE")]'
)
self.assertTrue(self.page.check_if_element_exist_by_xpath(
QueryToolLocators.sql_editor_message.format('CREATE TABLE')),
"CREATE TABLE message does not displayed")
self.page.clear_query_tool()
self._clear_query_tool()
query = """-- 1. (Done) END any open transaction.
-- 2. (Done) Enable auto rollback and disable auto commit.
-- 3. (Done) Create table in public schema.
@@ -576,18 +546,14 @@ CREATE TABLE public.{}();""".format(table_name)
-- 5. END transaction.
-- 6. Check if table is *NOT* created after ending transaction.
SELECT 1/0;"""
self.page.fill_codemirror_area_with(query)
self.page.find_by_css_selector(
QueryToolLocatorsCss.btn_execute_query).click()
self.page.execute_query(query)
self.page.wait_for_query_tool_loading_indicator_to_disappear()
self.page.click_tab('Messages')
self.page.find_by_xpath(
'//div[contains(@class, "sql-editor-message") and '
'contains(string(), "division by zero")]'
)
self.assertTrue(self.page.check_if_element_exist_by_xpath(
QueryToolLocators.sql_editor_message.format('division by zero')),
"division by zero message does not displayed")
self.page.clear_query_tool()
self._clear_query_tool()
query = """-- 1. (Done) END any open transaction.
-- 2. (Done) Enable auto rollback and disable auto commit.
-- 3. (Done) Create table in public schema.
@@ -595,19 +561,15 @@ SELECT 1/0;"""
-- 5. END transaction.
-- 6. Check if table is *NOT* created after ending transaction.
END;"""
self.page.fill_codemirror_area_with(query)
self.page.find_by_css_selector(
QueryToolLocatorsCss.btn_execute_query).click()
self.page.execute_query(query)
self.page.wait_for_query_tool_loading_indicator_to_disappear()
self.page.click_tab('Messages')
self.page.find_by_xpath(
'//div[contains(@class, "sql-editor-message") and '
'contains(string(), "Query returned successfully")]'
)
self.assertTrue(self.page.check_if_element_exist_by_xpath(
QueryToolLocators.sql_editor_message.
format('Query returned successfully')),
"Query returned successfully message does not displayed")
self.page.clear_query_tool()
self._clear_query_tool()
query = """-- 1. (Done) END any open transaction.
-- 2. (Done) Enable auto rollback and disable auto commit.
-- 3. (Done) Create table in public schema.
@@ -616,18 +578,14 @@ END;"""
-- 6. Check if table is *NOT* created after ending transaction.
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_css_selector(
QueryToolLocatorsCss.btn_execute_query).click()
self.page.execute_query(query)
self.page.wait_for_query_tool_loading_indicator_to_disappear()
self.page.click_tab('Data Output')
canvas = wait.until(EC.presence_of_element_located(
(By.CSS_SELECTOR, "#datagrid .slick-viewport .grid-canvas")))
canvas = self.wait.until(EC.presence_of_element_located(
(By.CSS_SELECTOR, QueryToolLocators.query_output_canvas_css)))
el = canvas.find_elements_by_xpath(
"//div[contains(@class, 'slick-cell') and "
"contains(text(), '{}')]".format(table_name))
QueryToolLocators.output_column_data_xpath.format(table_name))
assert len(el) == 0, "Table '{}' created even after ROLLBACK due to " \
"sql error.".format(table_name)
@@ -648,7 +606,7 @@ SELECT 1, pg_sleep(300)"""
commit_button.click()
query_op = self.page.find_by_css_selector(
QueryToolLocatorsCss.btn_query_dropdown)
QueryToolLocators.btn_query_dropdown)
query_op.click()
# enable auto-commit and disable auto-rollback
@@ -658,18 +616,18 @@ SELECT 1, pg_sleep(300)"""
query_op.click()
self.page.find_by_css_selector(
QueryToolLocatorsCss.btn_execute_query).click()
QueryToolLocators.btn_execute_query_css).click()
self.page.find_by_xpath("//*[@id='fetching_data']")
self.page.find_by_css_selector(
QueryToolLocatorsCss.btn_cancel_query).click()
QueryToolLocators.btn_cancel_query).click()
self.page.wait_for_query_tool_loading_indicator_to_disappear()
self.page.click_tab('Messages')
self.page.find_by_xpath(
self.assertTrue(self.page.check_if_element_exist_by_xpath(
'//div[contains(@class, "sql-editor-message") and '
'(contains(string(), "canceling statement due to user request") '
'or contains(string(), "Execution Cancelled!"))]'
)
))
def _supported_server_version(self):
connection = test_utils.get_db_connection(
@@ -683,48 +641,33 @@ SELECT 1, pg_sleep(300)"""
return connection.server_version > 90100
def _query_tool_notify_statements(self):
wait = WebDriverWait(self.page.driver, 60)
print("\n\tListen on an event... ", file=sys.stderr, end="")
self.page.fill_codemirror_area_with("LISTEN foo;")
self.page.find_by_css_selector(
QueryToolLocatorsCss.btn_execute_query).click()
self.page.wait_for_query_tool_loading_indicator_to_disappear()
self.page.execute_query("LISTEN foo;")
self.page.click_tab('Messages')
wait.until(EC.text_to_be_present_in_element(
(By.CSS_SELECTOR, ".sql-editor-message"), "LISTEN")
)
self.assertTrue(self.page.check_if_element_exist_by_xpath(
QueryToolLocators.sql_editor_message.format('LISTEN')),
"LISTEN message does not displayed")
print("OK.", file=sys.stderr)
self._clear_query_tool()
self.page.clear_query_tool()
print("\tNotify event without data... ", file=sys.stderr, end="")
self.page.fill_codemirror_area_with("NOTIFY foo;")
self.page.find_by_css_selector(
QueryToolLocatorsCss.btn_execute_query).click()
self.page.wait_for_query_tool_loading_indicator_to_disappear()
self.page.execute_query("NOTIFY foo;")
self.page.click_tab('Notifications')
wait.until(EC.text_to_be_present_in_element(
self.wait.until(EC.text_to_be_present_in_element(
(By.CSS_SELECTOR, "td.channel"), "foo")
)
print("OK.", file=sys.stderr)
self._clear_query_tool()
self.page.clear_query_tool()
print("\tNotify event with data... ", file=sys.stderr, end="")
if self._supported_server_version():
self.page.fill_codemirror_area_with("SELECT pg_notify('foo', "
"'Hello')")
self.page.find_by_css_selector(
QueryToolLocatorsCss.btn_execute_query).click()
self.page.wait_for_query_tool_loading_indicator_to_disappear()
self.page.execute_query("SELECT pg_notify('foo', 'Hello')")
self.page.click_tab('Notifications')
wait.until(WaitForAnyElementWithText(
self.wait.until(WaitForAnyElementWithText(
(By.CSS_SELECTOR, 'td.payload'), "Hello"))
print("OK.", file=sys.stderr)
self._clear_query_tool()
self.page.clear_query_tool()
else:
print("Skipped.", file=sys.stderr)
@@ -756,69 +699,63 @@ SELECT 1, pg_sleep(300)"""
is_edb = 'EnterpriseDB' in version_string[0]
connection.close()
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_css_selector(
QueryToolLocatorsCss.btn_execute_query).click()
self.page.wait_for_query_tool_loading_indicator_to_disappear()
self._clear_query_tool()
self.page.execute_query("SET jit_above_cost=10;")
self.page.clear_query_tool()
self.page.fill_codemirror_area_with("SELECT count(*) FROM pg_class;")
explain_op = self.page.find_by_css_selector(
QueryToolLocatorsCss.btn_explain_options_dropdown)
QueryToolLocators.btn_explain_options_dropdown)
explain_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):
for op in (QueryToolLocators.btn_explain_verbose,
QueryToolLocators.btn_explain_costs,
QueryToolLocators.btn_explain_buffers,
QueryToolLocators.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)
QueryToolLocators.btn_explain_costs)
cost_btn.click()
# close explain options
explain_op.click()
self.page.find_by_css_selector(
QueryToolLocatorsCss.btn_explain_analyze).click()
QueryToolLocators.btn_explain_analyze).click()
self.page.wait_for_query_tool_loading_indicator_to_disappear()
self.page.click_tab('Data Output')
canvas = wait.until(EC.presence_of_element_located(
(By.CSS_SELECTOR, "#datagrid .slick-viewport .grid-canvas"))
canvas = self.wait.until(EC.presence_of_element_located(
(By.CSS_SELECTOR, QueryToolLocators.query_output_canvas_css))
)
# Search for 'Output' word in result (verbose option)
canvas.find_element_by_xpath("//*[contains(string(), 'JIT')]")
self._clear_query_tool()
self.page.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)
QueryToolLocators.btn_auto_commit_check_status)
if 'visibility-hidden' in check_status.get_attribute('class'):
self.page.find_by_css_selector(QueryToolLocatorsCss.
self.page.find_by_css_selector(QueryToolLocators.
btn_auto_commit).click()
if option == 'auto_rollback':
check_status = self.driver.find_element_by_css_selector(
QueryToolLocatorsCss.btn_auto_rollback_check_status)
QueryToolLocators.btn_auto_rollback_check_status)
if 'visibility-hidden' in check_status.get_attribute('class'):
self.page.find_by_css_selector(QueryToolLocatorsCss.
self.page.find_by_css_selector(QueryToolLocators.
btn_auto_rollback).click()
def uncheck_execute_option(self, option):
@@ -826,15 +763,15 @@ SELECT 1, pg_sleep(300)"""
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)
QueryToolLocators.btn_auto_commit_check_status)
if 'visibility-hidden' not in check_status.get_attribute('class'):
self.page.find_by_css_selector(QueryToolLocatorsCss.
self.page.find_by_css_selector(QueryToolLocators.
btn_auto_commit).click()
if option == 'auto_rollback':
check_status = self.driver.find_element_by_css_selector(
QueryToolLocatorsCss.btn_auto_rollback_check_status)
QueryToolLocators.btn_auto_rollback_check_status)
if 'visibility-hidden' not in check_status.get_attribute('class'):
self.page.find_by_css_selector(QueryToolLocatorsCss.
self.page.find_by_css_selector(QueryToolLocators.
btn_auto_rollback).click()

View File

@@ -40,9 +40,13 @@ class TableDdlFeatureTest(BaseFeatureTest):
self.page.select_tree_item(self.test_table_name)
self.page.click_tab("SQL")
self.page.find_by_xpath(
# Wait till data is displayed in SQL Tab
self.assertTrue(self.page.check_if_element_exist_by_xpath(
"//*[contains(@class,'CodeMirror-lines') and "
"contains(.,'CREATE TABLE public.%s')]" % self.test_table_name)
"contains(.,'CREATE TABLE public.%s')]" % self.test_table_name,
10), "No data displayed in SQL tab")
def after(self):
self.page.remove_server(self.server)
test_utils.delete_table(
self.server, self.test_db, self.test_table_name)

View File

@@ -18,7 +18,8 @@ from selenium.webdriver.common.by import By
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.ui import WebDriverWait
from .locators import QueryToolLocatorsCss
from regression.feature_utils.locators import QueryToolLocators, \
NavMenuLocators
CURRENT_PATH = os.path.dirname(os.path.realpath(__file__))
@@ -26,8 +27,6 @@ config_data = config_data_json = {}
# try:
with open(CURRENT_PATH + '/test_data.json') as data_file:
config_data_json = json.load(data_file)
# except Exception as e:
# print(str(e))
class CheckForViewDataTest(BaseFeatureTest):
@@ -121,7 +120,13 @@ CREATE TABLE public.nonintpkey
def runTest(self):
self.page.wait_for_spinner_to_disappear()
self.page.add_server(self.server)
self._tables_node_expandable()
self.page.toggle_open_tree_item(self.server['name'])
self.page.toggle_open_tree_item('Databases')
self.page.toggle_open_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._load_config_data('table_insert_update_cases')
# iterate on both tables
@@ -134,6 +139,10 @@ CREATE TABLE public.nonintpkey
def after(self):
self.page.remove_server(self.server)
for cnt in (1, 2):
test_utils.delete_table(
self.server, self.test_db, 'defaults_{0}'.format(str(cnt)))
test_utils.delete_table(self.server, self.test_db, 'nonintpkey')
@staticmethod
def _get_cell_xpath(cell, row):
@@ -227,14 +236,14 @@ CREATE TABLE public.nonintpkey
send_keys(Keys.ENTER).perform()
elif cell_type in ['text', 'json', 'text[]', 'boolean[]']:
text_area_ele = self.page.find_by_css_selector(
".pg-text-editor > textarea")
QueryToolLocators.row_editor_text_area_css)
text_area_ele.clear()
text_area_ele.click()
text_area_ele.send_keys(value)
# Click on editor's Save button
self.page.find_by_css_selector(
'.btn.btn-primary.long_text_editor').click()
QueryToolLocators.text_editor_ok_btn_css).click()
else:
# Boolean editor test for to True click
if data[1] == 'true':
@@ -250,24 +259,19 @@ CREATE TABLE public.nonintpkey
# Sets false
ActionChains(self.driver).click(checkbox_el).perform()
def _tables_node_expandable(self):
self.page.toggle_open_tree_item(self.server['name'])
self.page.toggle_open_tree_item('Databases')
self.page.toggle_open_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')
def _view_data_grid(self, table_name):
self.page.driver.find_element_by_link_text("Object").click()
ActionChains(
self.page.driver
).move_to_element(
self.page.driver.find_element_by_link_text("View/Edit Data")
self.page.driver.find_element_by_link_text(
NavMenuLocators.view_data_link_text)
).perform()
self.page.find_by_partial_link_text("All Rows").click()
time.sleep(1)
# wait until datagrid frame is loaded.
self.page.wait_for_query_tool_loading_indicator_to_appear()
self.page.wait_for_query_tool_loading_indicator_to_disappear()
self.page.click_tab(table_name)
@@ -284,8 +288,10 @@ CREATE TABLE public.nonintpkey
row0_cell0_xpath = CheckForViewDataTest._get_cell_xpath("r0", 1)
self.page.find_by_xpath(row0_cell0_xpath).click()
self.page.find_by_xpath("//*[@id='btn-copy-row']").click()
self.page.find_by_xpath("//*[@id='btn-paste-row']").click()
self.page.find_by_css_selector(
QueryToolLocators.copy_button_css).click()
self.page.find_by_css_selector(
QueryToolLocators.paste_button_css).click()
# Update primary key of copied cell
self._add_update_save_row(config_data['copy'], row=2)
@@ -305,7 +311,7 @@ CREATE TABLE public.nonintpkey
time.sleep(0.2)
self._update_cell(cell_xpath, data[str(idx)])
self.page.find_by_css_selector(
QueryToolLocatorsCss.btn_save_data).click()
QueryToolLocators.btn_save_data).click()
# There should be some delay after save button is clicked, as it
# takes some time to complete save ajax call otherwise discard unsaved
# changes dialog will appear if we try to execute query before previous
@@ -320,11 +326,12 @@ CREATE TABLE public.nonintpkey
def _verify_messsages(self, text):
messages_ele = self.page.find_by_css_selector(
QueryToolLocatorsCss.query_messages_panel)
QueryToolLocators.query_messages_panel)
self.assertEquals(text, messages_ele.text)
def _verify_row_data(self, is_new_row, config_check_data):
self.page.find_by_id("btn-flash").click()
self.page.find_by_css_selector(
QueryToolLocators.btn_execute_query_css).click()
# First row if row height = 0, second row if its 25
row_height = 0 if is_new_row else 25

View File

@@ -8,10 +8,13 @@
##########################################################################
from __future__ import print_function
import sys
import random
from regression.python_test_utils import test_utils
from regression.feature_utils.base_feature_test import BaseFeatureTest
from selenium.webdriver import ActionChains
import sys
from selenium.common.exceptions import StaleElementReferenceException
from regression.feature_utils.locators import QueryToolLocators
class CheckForXssFeatureTest(BaseFeatureTest):
@@ -32,7 +35,8 @@ class CheckForXssFeatureTest(BaseFeatureTest):
scenarios = [
("Test XSS check for panels and query tool", dict())
]
test_table_name = "<h1>X"
test_table_name = "<h1>X" + str(random.randint(1000, 3000))
# test_table_name = "<h1>X"
test_type_name = '"<script>alert(1)</script>"'
def before(self):
@@ -85,6 +89,8 @@ class CheckForXssFeatureTest(BaseFeatureTest):
def after(self):
self.page.remove_server(self.server)
test_utils.delete_table(
self.server, self.test_db, self.test_table_name)
def _tables_node_expandable(self):
self.page.toggle_open_server(self.server['name'])
@@ -198,7 +204,8 @@ class CheckForXssFeatureTest(BaseFeatureTest):
self.page.fill_codemirror_area_with(
"select '<script>alert(1)</script>"
)
self.page.find_by_id("btn-flash").click()
self.page.find_by_css_selector(
QueryToolLocators.btn_execute_query_css).click()
self.page.click_tab('Query History')
@@ -227,13 +234,17 @@ class CheckForXssFeatureTest(BaseFeatureTest):
'&lt;script&gt;alert(1)&lt;/script&gt;',
"Query tool (History Details-Message)"
)
# Check for history details error message
history_ele = self.page.find_by_css_selector(
".query-detail .history-error-text"
)
source_code = history_ele.get_attribute('innerHTML')
retry = 2
while retry > 0:
try:
# Check for history details error message
history_ele = self.page.find_by_css_selector(
".query-detail .history-error-text"
)
source_code = history_ele.get_attribute('innerHTML')
break
except StaleElementReferenceException:
retry -= 1
self._check_escaped_characters(
source_code,
@@ -272,7 +283,8 @@ class CheckForXssFeatureTest(BaseFeatureTest):
'select * from "{0}"'.format(self.test_table_name)
)
self.page.find_by_id("btn-explain").click()
self.page.find_by_css_selector(
QueryToolLocators.btn_explain).click()
self.page.wait_for_query_tool_loading_indicator_to_disappear()
self.page.click_tab('Explain')

View File

@@ -88,7 +88,18 @@ class CheckDebuggerForXssFeatureTest(BaseFeatureTest):
# If debugger plugin is not found
if is_error and is_error.text == "Debugger Error":
self.page.click_modal('OK')
click = True
while click:
try:
self.page.click_modal('OK')
wait.until(EC.invisibility_of_element(
(By.XPATH, "//div[contains(@class, 'alertify') and "
"not(contains(@class, 'ajs-hidden'))]//div["
"contains(@class,'ajs-header')]")
))
click = False
except TimeoutException:
pass
self.skipTest(
"Please make sure that debugger plugin is properly configured"
)

View File

@@ -10,6 +10,10 @@ import random
from regression.python_test_utils import test_utils
from regression.feature_utils.base_feature_test import BaseFeatureTest
from regression.feature_utils.locators import NavMenuLocators
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.ui import WebDriverWait
class CheckRoleMembershipControlFeatureTest(BaseFeatureTest):
@@ -36,6 +40,7 @@ class CheckRoleMembershipControlFeatureTest(BaseFeatureTest):
self.role)
test_utils.create_role(self.server, "postgres",
"<h1>test</h1>")
self.wait = WebDriverWait(self.page.driver, 20)
def runTest(self):
self.page.wait_for_spinner_to_disappear()
@@ -56,9 +61,11 @@ class CheckRoleMembershipControlFeatureTest(BaseFeatureTest):
self.page.select_tree_item(role)
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.driver.find_element_by_link_text(
NavMenuLocators.object_menu_link_text).click()
property_object = self.wait.until(EC.visibility_of_element_located(
(By.CSS_SELECTOR, NavMenuLocators.properties_obj_css)))
property_object.click()
self.click_membership_tab()
# Fetch the source code for our custom control
source_code = self.page.find_by_xpath(