Stabilise feature tests for continuous running on CI systems. Fixes #3136.

This commit is contained in:
Usman Muzaffar 2018-08-21 17:39:36 +05:30 committed by Akshay Joshi
parent 57660d131f
commit 70c95fcdd5
14 changed files with 193 additions and 206 deletions

View File

@ -15,6 +15,7 @@ Features
Bug fixes Bug fixes
********* *********
| `Bug #3136 <https://redmine.postgresql.org/issues/3136>`_ - Stabilise feature tests for continuous running on CI systems.
| `Bug #3325 <https://redmine.postgresql.org/issues/3325>`_ - Fix sort/filter dialog issue where it incorrectly requires ASC/DESC. | `Bug #3325 <https://redmine.postgresql.org/issues/3325>`_ - Fix sort/filter dialog issue where it incorrectly requires ASC/DESC.
| `Bug #3407 <https://redmine.postgresql.org/issues/3407>`_ - Fix keyboard shortcuts layout in the preferences panel. | `Bug #3407 <https://redmine.postgresql.org/issues/3407>`_ - Fix keyboard shortcuts layout in the preferences panel.
| `Bug #3461 <https://redmine.postgresql.org/issues/3461>`_ - Ensure that refreshing a node also updates the Property list. | `Bug #3461 <https://redmine.postgresql.org/issues/3461>`_ - Ensure that refreshing a node also updates the Property list.

View File

@ -8,10 +8,10 @@
########################################################################## ##########################################################################
import pyperclip import pyperclip
import random
from selenium.webdriver import ActionChains from selenium.webdriver import ActionChains
from selenium.webdriver.common.keys import Keys from selenium.webdriver.common.keys import Keys
from regression.python_test_utils import test_utils from regression.python_test_utils import test_utils
from regression.feature_utils.base_feature_test import BaseFeatureTest from regression.feature_utils.base_feature_test import BaseFeatureTest
@ -25,32 +25,29 @@ class CopySelectedQueryResultsFeatureTest(BaseFeatureTest):
("Copy rows, column using button and keyboard shortcut", dict()) ("Copy rows, column using button and keyboard shortcut", dict())
] ]
test_table_name = ""
def before(self): def before(self):
connection = test_utils.get_db_connection(
self.server['db'], # Create test table with random name to avoid same name conflicts in
self.server['username'], # parallel execution
self.server['db_password'], self.test_table_name = "test_table" + str(random.randint(1000, 3000))
self.server['host'],
self.server['port'],
self.server['sslmode']
)
test_utils.drop_database(connection, "acceptance_test_db")
test_utils.create_database(self.server, "acceptance_test_db")
test_utils.create_table( test_utils.create_table(
self.server, "acceptance_test_db", "test_table") self.server, self.test_db, self.test_table_name)
self.page.add_server(self.server) self.page.add_server(self.server)
def runTest(self): def runTest(self):
self.page.toggle_open_tree_item(self.server['name']) self.page.toggle_open_tree_item(self.server['name'])
self.page.toggle_open_tree_item('Databases') self.page.toggle_open_tree_item('Databases')
self.page.toggle_open_tree_item('acceptance_test_db') self.page.toggle_open_tree_item(self.test_db)
self.page.open_query_tool() self.page.open_query_tool()
self.page.driver.switch_to_frame( self.page.driver.switch_to_frame(
self.page.driver.find_element_by_tag_name("iframe")) self.page.driver.find_element_by_tag_name("iframe"))
self.page.fill_codemirror_area_with( self.page.fill_codemirror_area_with(
"SELECT * FROM test_table ORDER BY some_column") "SELECT * FROM %s ORDER BY some_column" % self.test_table_name)
self.page.find_by_id("btn-flash").click() self.page.find_by_id("btn-flash").click()
@ -205,13 +202,3 @@ class CopySelectedQueryResultsFeatureTest(BaseFeatureTest):
def after(self): def after(self):
self.page.close_query_tool() self.page.close_query_tool()
self.page.remove_server(self.server) self.page.remove_server(self.server)
connection = test_utils.get_db_connection(
self.server['db'],
self.server['username'],
self.server['db_password'],
self.server['host'],
self.server['port'],
self.server['sslmode']
)
test_utils.drop_database(connection, "acceptance_test_db")

View File

@ -11,11 +11,11 @@ from __future__ import print_function
import os import os
import time import time
import sys import sys
from selenium.webdriver.common.keys import Keys from selenium.webdriver.common.keys import Keys
from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.common.by import By from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC from selenium.webdriver.support import expected_conditions as EC
from regression.python_test_utils import test_utils
from regression.feature_utils.base_feature_test import BaseFeatureTest from regression.feature_utils.base_feature_test import BaseFeatureTest
@ -28,15 +28,11 @@ class CheckFileManagerFeatureTest(BaseFeatureTest):
] ]
def before(self): def before(self):
connection = test_utils.get_db_connection( if os.name == 'nt':
self.server['db'], self.skipTest("This test is skipped for Windows. As Windows "
self.server['username'], "does not allow the '<' and '>' character while "
self.server['db_password'], "specifying the file name.")
self.server['host'],
self.server['port']
)
test_utils.drop_database(connection, "acceptance_test_db")
test_utils.create_database(self.server, "acceptance_test_db")
self.page.add_server(self.server) self.page.add_server(self.server)
self.wait = WebDriverWait(self.page.driver, 10) self.wait = WebDriverWait(self.page.driver, 10)
self.XSS_FILE = '/tmp/<img src=x onmouseover=alert("1")>.sql' self.XSS_FILE = '/tmp/<img src=x onmouseover=alert("1")>.sql'
@ -47,14 +43,6 @@ class CheckFileManagerFeatureTest(BaseFeatureTest):
def after(self): def after(self):
self.page.close_query_tool('sql', False) self.page.close_query_tool('sql', False)
self.page.remove_server(self.server) self.page.remove_server(self.server)
connection = test_utils.get_db_connection(
self.server['db'],
self.server['username'],
self.server['db_password'],
self.server['host'],
self.server['port']
)
test_utils.drop_database(connection, "acceptance_test_db")
def runTest(self): def runTest(self):
print("Tests to check if File manager is vulnerable to XSS... ", print("Tests to check if File manager is vulnerable to XSS... ",
@ -72,7 +60,7 @@ class CheckFileManagerFeatureTest(BaseFeatureTest):
def _navigate_to_query_tool(self): def _navigate_to_query_tool(self):
self.page.toggle_open_tree_item(self.server['name']) self.page.toggle_open_tree_item(self.server['name'])
self.page.toggle_open_tree_item('Databases') self.page.toggle_open_tree_item('Databases')
self.page.toggle_open_tree_item('acceptance_test_db') self.page.toggle_open_tree_item(self.test_db)
self.page.open_query_tool() self.page.open_query_tool()
def _create_new_file(self): def _create_new_file(self):
@ -145,20 +133,49 @@ class CheckFileManagerFeatureTest(BaseFeatureTest):
# Added time.sleep so that the element to be clicked. # Added time.sleep so that the element to be clicked.
time.sleep(0.05) time.sleep(0.05)
self.page.find_by_css_selector("#contents th[data-column='0']").click()
# Check for sort Ascending # Intermittently facing issue on first click it is not successful
self.wait.until( # so tried couple of times.
EC.presence_of_element_located(( iteration = 0
By.CSS_SELECTOR, success = False
"#contents th[data-column='0'].tablesorter-headerAsc") while not success and iteration < 4:
) self.page.find_by_xpath("//th[@data-column='0']"
) "/div/span[text()='Name']").click()
# Check for sort Ascending
try:
self.wait.until(
EC.presence_of_element_located((
By.CSS_SELECTOR,
"#contents th[data-column='0'].tablesorter-headerAsc")
))
success = True
except Exception as e:
iteration += 1
if not success:
raise Exception("Unable to sort in ascending order while clicked "
"on 'Name' column")
time.sleep(0.05)
# Click and Check for sort Descending # Click and Check for sort Descending
self.page.find_by_css_selector("#contents th[data-column='0']").click() # Intermittently facing issue on first click it is not successful
self.wait.until( # so tried couple of times.
EC.presence_of_element_located(( iteration = 0
By.CSS_SELECTOR, success = False
"#contents th[data-column='0'].tablesorter-headerDesc") while not success and iteration < 4:
) self.page.find_by_xpath("//th[@data-column='0']"
) "/div/span[text()='Name']").click()
try:
self.wait.until(
EC.presence_of_element_located((
By.CSS_SELECTOR,
"#contents th[data-column='0'].tablesorter-headerDesc")
))
success = True
except Exception as e:
iteration += 1
if not success:
raise Exception("Unable to sort in descending order while clicked "
"on 'Name' column")

View File

@ -10,6 +10,7 @@
import os import os
import json import json
import time import time
from selenium.common.exceptions import TimeoutException from selenium.common.exceptions import TimeoutException
from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC from selenium.webdriver.support import expected_conditions as EC
@ -18,7 +19,6 @@ from selenium.webdriver import ActionChains
from regression.python_test_utils import test_utils from regression.python_test_utils import test_utils
from regression.feature_utils.base_feature_test import BaseFeatureTest from regression.feature_utils.base_feature_test import BaseFeatureTest
CURRENT_PATH = os.path.dirname(os.path.realpath(__file__)) CURRENT_PATH = os.path.dirname(os.path.realpath(__file__))
try: try:
@ -48,8 +48,7 @@ class PGDataypeFeatureTest(BaseFeatureTest):
self.server['db_password'], self.server['db_password'],
self.server['host'], self.server['host'],
self.server['port'], self.server['port'],
self.server['sslmode'] self.server['sslmode'])
)
self.timezone = int(test_utils.get_timezone_without_dst(connection)) self.timezone = int(test_utils.get_timezone_without_dst(connection))
@ -66,9 +65,6 @@ class PGDataypeFeatureTest(BaseFeatureTest):
else: else:
self.timezone_hh_mm = '+{}'.format(self.timezone_hh_mm) self.timezone_hh_mm = '+{}'.format(self.timezone_hh_mm)
test_utils.drop_database(connection, "acceptance_test_db")
test_utils.create_database(self.server, "acceptance_test_db")
self.database_version = connection.server_version self.database_version = connection.server_version
# For this test case we need to set "Insert bracket pairs?" # For this test case we need to set "Insert bracket pairs?"
@ -76,6 +72,9 @@ class PGDataypeFeatureTest(BaseFeatureTest):
# to add matching closing bracket by it self. # to add matching closing bracket by it self.
self._update_preferences() self._update_preferences()
# close the db connection
connection.close()
def _update_preferences(self): def _update_preferences(self):
self.page.find_by_id("mnu_file").click() self.page.find_by_id("mnu_file").click()
self.page.find_by_id("mnu_preferences").click() self.page.find_by_id("mnu_preferences").click()
@ -137,32 +136,24 @@ class PGDataypeFeatureTest(BaseFeatureTest):
def after(self): def after(self):
self.page.remove_server(self.server) self.page.remove_server(self.server)
connection = test_utils.get_db_connection(
self.server['db'],
self.server['username'],
self.server['db_password'],
self.server['host'],
self.server['port'],
self.server['sslmode']
)
test_utils.drop_database(connection, "acceptance_test_db")
def _schema_node_expandable(self): def _schema_node_expandable(self):
self.page.toggle_open_tree_item(self.server['name']) self.page.toggle_open_tree_item(self.server['name'])
self.page.toggle_open_tree_item('Databases') self.page.toggle_open_tree_item('Databases')
self.page.toggle_open_tree_item('acceptance_test_db') self.page.toggle_open_tree_item(self.test_db)
def _check_datatype(self): def _check_datatype(self):
# Slick grid does not render all the column if viewport is not enough # Slick grid does not render all the column if viewport is not enough
# wide. So execute test as batch of queries. # wide. So execute test as batch of queries.
self.page.select_tree_item(self.test_db)
self.page.open_query_tool() self.page.open_query_tool()
self._create_enum_type() self._create_enum_type()
for batch in config_data: for batch in config_data:
query = self.construct_select_query(batch) query = self.construct_select_query(batch)
self.page.fill_codemirror_area_with(query) self.page.fill_codemirror_area_with(query)
self.page.find_by_id("btn-flash").click() self.page.find_by_id("btn-flash").click()
wait = WebDriverWait(self.page.driver, 5)
wait = WebDriverWait(self.page.driver, 5)
wait.until(EC.presence_of_element_located( wait.until(EC.presence_of_element_located(
(By.XPATH, (By.XPATH,
"//*[contains(@class,'column-type') and " "//*[contains(@class,'column-type') and "

View File

@ -8,6 +8,7 @@
########################################################################## ##########################################################################
import pyperclip import pyperclip
import random
from selenium.webdriver import ActionChains from selenium.webdriver import ActionChains
from selenium.webdriver.common.keys import Keys from selenium.webdriver.common.keys import Keys
@ -25,26 +26,18 @@ class QueryToolJourneyTest(BaseFeatureTest):
("Tests the path through the query tool", dict()) ("Tests the path through the query tool", dict())
] ]
test_table_name = ""
def before(self): def before(self):
connection = test_utils.get_db_connection( self.test_table_name = "test_table" + str(random.randint(1000, 3000))
self.server['db'],
self.server['username'],
self.server['db_password'],
self.server['host'],
self.server['port']
)
test_utils.drop_database(connection, "acceptance_test_db")
test_utils.create_database(self.server, "acceptance_test_db")
test_utils.create_table( test_utils.create_table(
self.server, "acceptance_test_db", "test_table") self.server, self.test_db, self.test_table_name)
self.page.add_server(self.server) self.page.add_server(self.server)
def runTest(self): def runTest(self):
self._navigate_to_query_tool() self._navigate_to_query_tool()
self._execute_query( self._execute_query(
"SELECT * FROM test_table ORDER BY value" "SELECT * FROM %s ORDER BY value " % self.test_table_name)
)
self._test_copies_rows() self._test_copies_rows()
self._test_copies_columns() self._test_copies_columns()
@ -100,11 +93,18 @@ class QueryToolJourneyTest(BaseFeatureTest):
.perform() .perform()
selected_history_entry = self.page.find_by_css_selector( selected_history_entry = self.page.find_by_css_selector(
"#query_list .selected") "#query_list .selected")
self.assertIn("SELECT * FROM test_table ORDER BY value", self.assertIn(("SELECT * FROM %s ORDER BY value" %
self.test_table_name),
selected_history_entry.text) selected_history_entry.text)
selected_history_detail_pane = self.page.find_by_id("query_detail")
self.assertIn("SELECT * FROM test_table ORDER BY value", query_element = self.page.driver.\
selected_history_detail_pane.text) find_element_by_xpath(
"//div[@id='history_grid']//div[@class='entry selected']"
"/div[@class='query']")
self.assertIn(("SELECT * FROM %s ORDER BY value"
% self.test_table_name), query_element.text)
newly_selected_history_entry = self.page.find_by_xpath( newly_selected_history_entry = self.page.find_by_xpath(
"//*[@id='query_list']/ul/li[2]") "//*[@id='query_list']/ul/li[2]")
self.page.click_element(newly_selected_history_entry) self.page.click_element(newly_selected_history_entry)
@ -167,7 +167,7 @@ class QueryToolJourneyTest(BaseFeatureTest):
def _navigate_to_query_tool(self): def _navigate_to_query_tool(self):
self.page.toggle_open_tree_item(self.server['name']) self.page.toggle_open_tree_item(self.server['name'])
self.page.toggle_open_tree_item('Databases') self.page.toggle_open_tree_item('Databases')
self.page.toggle_open_tree_item('acceptance_test_db') self.page.toggle_open_tree_item(self.test_db)
self.page.open_query_tool() self.page.open_query_tool()
def _execute_query(self, query): def _execute_query(self, query):
@ -180,10 +180,3 @@ class QueryToolJourneyTest(BaseFeatureTest):
def after(self): def after(self):
self.page.close_query_tool() self.page.close_query_tool()
self.page.remove_server(self.server) self.page.remove_server(self.server)
connection = test_utils.get_db_connection(self.server['db'],
self.server['username'],
self.server['db_password'],
self.server['host'],
self.server['port'])
test_utils.drop_database(connection, "acceptance_test_db")

View File

@ -8,7 +8,6 @@
########################################################################## ##########################################################################
from __future__ import print_function from __future__ import print_function
import time
import sys import sys
from selenium.common.exceptions import StaleElementReferenceException from selenium.common.exceptions import StaleElementReferenceException
@ -32,20 +31,11 @@ class QueryToolFeatureTest(BaseFeatureTest):
] ]
def before(self): def before(self):
connection = test_utils.get_db_connection(
self.server['db'],
self.server['username'],
self.server['db_password'],
self.server['host'],
self.server['port'],
self.server['sslmode']
)
test_utils.drop_database(connection, "acceptance_test_db")
test_utils.create_database(self.server, "acceptance_test_db")
self.page.wait_for_spinner_to_disappear() self.page.wait_for_spinner_to_disappear()
self.page.add_server(self.server) self.page.add_server(self.server)
self._locate_database_tree_node() self._locate_database_tree_node()
self.page.open_query_tool() self.page.open_query_tool()
self.page.wait_for_spinner_to_disappear()
self._reset_options() self._reset_options()
def runTest(self): def runTest(self):
@ -116,15 +106,6 @@ class QueryToolFeatureTest(BaseFeatureTest):
def after(self): def after(self):
self.page.remove_server(self.server) self.page.remove_server(self.server)
connection = test_utils.get_db_connection(
self.server['db'],
self.server['username'],
self.server['db_password'],
self.server['host'],
self.server['port'],
self.server['sslmode']
)
test_utils.drop_database(connection, "acceptance_test_db")
def _reset_options(self): def _reset_options(self):
# this will set focus to correct iframe. # this will set focus to correct iframe.
@ -135,6 +116,10 @@ class QueryToolFeatureTest(BaseFeatureTest):
ActionChains(self.driver).move_to_element( ActionChains(self.driver).move_to_element(
query_op.find_element_by_xpath( query_op.find_element_by_xpath(
"//li[contains(.,'Explain Options')]")).perform() "//li[contains(.,'Explain Options')]")).perform()
self.page.driver.execute_script(
"arguments[0].scrollIntoView()",
self.page.find_by_xpath(
"//span[normalize-space(text())='Verbose']"))
# disable Explain options and auto rollback only if they are enabled. # disable Explain options and auto rollback only if they are enabled.
for op in ('explain-verbose', 'explain-costs', for op in ('explain-verbose', 'explain-costs',
@ -156,7 +141,7 @@ class QueryToolFeatureTest(BaseFeatureTest):
def _locate_database_tree_node(self): def _locate_database_tree_node(self):
self.page.toggle_open_tree_item(self.server['name']) self.page.toggle_open_tree_item(self.server['name'])
self.page.toggle_open_tree_item('Databases') self.page.toggle_open_tree_item('Databases')
self.page.toggle_open_tree_item('acceptance_test_db') self.page.toggle_open_tree_item(self.test_db)
def _clear_query_tool(self): def _clear_query_tool(self):
self.page.click_element( self.page.click_element(
@ -187,8 +172,6 @@ SELECT generate_series(1, {}) as id1, 'dummy' as id2""".format(
self.page.find_by_id("btn-flash").click() self.page.find_by_id("btn-flash").click()
# self.page.wait_for_query_tool_loading_indicator_to_disappear()
wait.until(EC.presence_of_element_located( wait.until(EC.presence_of_element_located(
(By.XPATH, (By.XPATH,
'//span[@data-row="0" and text()="1"]')) '//span[@data-row="0" and text()="1"]'))
@ -210,8 +193,6 @@ SELECT generate_series(1, {}) as id1, 'dummy' as id2""".format(
file=sys.stderr, end="") file=sys.stderr, end="")
self.page.find_by_id("btn-flash").click() self.page.find_by_id("btn-flash").click()
# self.page.wait_for_query_tool_loading_indicator_to_disappear()
wait.until(EC.presence_of_element_located( wait.until(EC.presence_of_element_located(
(By.XPATH, (By.XPATH,
'//span[@data-row="0" and text()="1"]')) '//span[@data-row="0" and text()="1"]'))
@ -230,7 +211,7 @@ SELECT generate_series(1, {}) as id1, 'dummy' as id2""".format(
file=sys.stderr, end="") file=sys.stderr, end="")
self.page.find_by_id("btn-flash").click() self.page.find_by_id("btn-flash").click()
# self.page.wait_for_query_tool_loading_indicator_to_disappear() self.page.wait_for_query_tool_loading_indicator_to_disappear()
wait.until(EC.presence_of_element_located( wait.until(EC.presence_of_element_located(
(By.XPATH, (By.XPATH,
@ -275,6 +256,11 @@ SELECT generate_series(1, 1000) as id order by id desc"""
query_op.find_element_by_xpath( query_op.find_element_by_xpath(
"//li[contains(.,'Explain Options')]")).perform() "//li[contains(.,'Explain Options')]")).perform()
self.page.driver.execute_script(
"arguments[0].scrollIntoView()",
self.page.find_by_xpath(
"//span[normalize-space(text())='Verbose']"))
self.page.find_by_id("btn-explain-verbose").click() self.page.find_by_id("btn-explain-verbose").click()
self.page.find_by_id("btn-explain-costs").click() self.page.find_by_id("btn-explain-costs").click()
@ -310,6 +296,11 @@ SELECT generate_series(1, 1000) as id order by id desc"""
query_op.find_element_by_xpath( query_op.find_element_by_xpath(
"//li[contains(.,'Explain Options')]")).perform() "//li[contains(.,'Explain Options')]")).perform()
self.page.driver.execute_script(
"arguments[0].scrollIntoView()",
self.page.find_by_xpath(
"//span[normalize-space(text())='Verbose']"))
self.page.find_by_id("btn-explain-buffers").click() self.page.find_by_id("btn-explain-buffers").click()
self.page.find_by_id("btn-explain-timing").click() self.page.find_by_id("btn-explain-timing").click()
@ -670,7 +661,6 @@ SELECT 1, pg_sleep(300)"""
wait.until(WaitForAnyElementWithText( wait.until(WaitForAnyElementWithText(
(By.CSS_SELECTOR, 'td.payload'), "Hello")) (By.CSS_SELECTOR, 'td.payload'), "Hello"))
print("OK.", file=sys.stderr) print("OK.", file=sys.stderr)
self._clear_query_tool()
else: else:
print("Skipped.", file=sys.stderr) print("Skipped.", file=sys.stderr)

View File

@ -7,6 +7,8 @@
# #
########################################################################## ##########################################################################
import random
from regression.feature_utils.base_feature_test import BaseFeatureTest from regression.feature_utils.base_feature_test import BaseFeatureTest
from regression.python_test_utils import test_utils from regression.python_test_utils import test_utils
@ -18,46 +20,29 @@ class TableDdlFeatureTest(BaseFeatureTest):
("Test table DDL generation", dict()) ("Test table DDL generation", dict())
] ]
def before(self): test_table_name = ""
connection = test_utils.get_db_connection(
self.server['db'],
self.server['username'],
self.server['db_password'],
self.server['host'],
self.server['port'],
self.server['sslmode']
)
test_utils.drop_database(connection, "acceptance_test_db")
test_utils.create_database(self.server, "acceptance_test_db") def before(self):
self.page.add_server(self.server) self.page.add_server(self.server)
def runTest(self): def runTest(self):
test_utils.create_table( self.test_table_name = "test_table" + str(random.randint(1000, 3000))
self.server, "acceptance_test_db", "test_table") test_utils.create_table(self.server, self.test_db,
self.test_table_name)
self.page.toggle_open_server(self.server['name']) self.page.toggle_open_server(self.server['name'])
self.page.toggle_open_tree_item('Databases') self.page.toggle_open_tree_item('Databases')
self.page.toggle_open_tree_item('acceptance_test_db') self.page.toggle_open_tree_item(self.test_db)
self.page.toggle_open_tree_item('Schemas') self.page.toggle_open_tree_item('Schemas')
self.page.toggle_open_tree_item('public') self.page.toggle_open_tree_item('public')
self.page.toggle_open_tree_item('Tables') self.page.toggle_open_tree_item('Tables')
self.page.select_tree_item('test_table') self.page.select_tree_item(self.test_table_name)
self.page.click_tab("SQL") self.page.click_tab("SQL")
self.page.find_by_xpath( self.page.find_by_xpath(
"//*[contains(@class,'CodeMirror-lines') and " "//*[contains(@class,'CodeMirror-lines') and "
"contains(.,'CREATE TABLE public.test_table')]") "contains(.,'CREATE TABLE public.%s')]" % self.test_table_name)
def after(self): def after(self):
self.page.remove_server(self.server) self.page.remove_server(self.server)
connection = test_utils.get_db_connection(
self.server['db'],
self.server['username'],
self.server['db_password'],
self.server['host'],
self.server['port'],
self.server['sslmode']
)
test_utils.drop_database(connection, "acceptance_test_db")

View File

@ -10,6 +10,7 @@
import json import json
import os import os
import time import time
from selenium.webdriver import ActionChains from selenium.webdriver import ActionChains
from regression.python_test_utils import test_utils from regression.python_test_utils import test_utils
from regression.feature_utils.base_feature_test import BaseFeatureTest from regression.feature_utils.base_feature_test import BaseFeatureTest
@ -87,27 +88,19 @@ CREATE TABLE public.defaults_{0}
"COLLATE is not present in PG versions below v9.1" "COLLATE is not present in PG versions below v9.1"
) )
connection = test_utils.get_db_connection(
self.server['db'],
self.server['username'],
self.server['db_password'],
self.server['host'],
self.server['port'],
self.server['sslmode']
)
test_utils.drop_database(connection, "acceptance_test_db")
test_utils.create_database(self.server, "acceptance_test_db")
# Create pre-requisite table # Create pre-requisite table
for k, v in {1: 'id', 2: '"ID"'}.items(): for k, v in {1: 'id', 2: '"ID"'}.items():
test_utils.create_table_with_query( test_utils.create_table_with_query(
self.server, self.server,
"acceptance_test_db", self.test_db,
CheckForViewDataTest.defaults_query.format(k, v)) CheckForViewDataTest.defaults_query.format(k, v))
# Initialize an instance of WebDriverWait with timeout of 3 seconds # Initialize an instance of WebDriverWait with timeout of 3 seconds
self.wait = WebDriverWait(self.driver, 3) self.wait = WebDriverWait(self.driver, 3)
# close the db connection
connection.close()
def runTest(self): def runTest(self):
self.page.wait_for_spinner_to_disappear() self.page.wait_for_spinner_to_disappear()
self.page.add_server(self.server) self.page.add_server(self.server)
@ -129,15 +122,6 @@ CREATE TABLE public.defaults_{0}
def after(self): def after(self):
self.page.remove_server(self.server) self.page.remove_server(self.server)
connection = test_utils.get_db_connection(
self.server['db'],
self.server['username'],
self.server['db_password'],
self.server['host'],
self.server['port'],
self.server['sslmode']
)
test_utils.drop_database(connection, "acceptance_test_db")
@staticmethod @staticmethod
def _get_cell_xpath(cell, row): def _get_cell_xpath(cell, row):
@ -227,7 +211,7 @@ CREATE TABLE public.defaults_{0}
def _tables_node_expandable(self): def _tables_node_expandable(self):
self.page.toggle_open_tree_item(self.server['name']) self.page.toggle_open_tree_item(self.server['name'])
self.page.toggle_open_tree_item('Databases') self.page.toggle_open_tree_item('Databases')
self.page.toggle_open_tree_item('acceptance_test_db') self.page.toggle_open_tree_item(self.test_db)
self.page.toggle_open_tree_item('Schemas') self.page.toggle_open_tree_item('Schemas')
self.page.toggle_open_tree_item('public') self.page.toggle_open_tree_item('public')
self.page.toggle_open_tree_item('Tables') self.page.toggle_open_tree_item('Tables')

View File

@ -29,26 +29,16 @@ class CheckForXssFeatureTest(BaseFeatureTest):
scenarios = [ scenarios = [
("Test XSS check for panels and query tool", dict()) ("Test XSS check for panels and query tool", dict())
] ]
test_table_name = "<h1>X"
def before(self): def before(self):
connection = test_utils.get_db_connection(
self.server['db'],
self.server['username'],
self.server['db_password'],
self.server['host'],
self.server['port'],
self.server['sslmode']
)
test_utils.drop_database(connection, "acceptance_test_db")
test_utils.create_database(self.server, "acceptance_test_db")
test_utils.create_table( test_utils.create_table(
self.server, "acceptance_test_db", "<h1>X" self.server, self.test_db, self.test_table_name
) )
# This is needed to test dependents tab (eg: BackGrid) # This is needed to test dependents tab (eg: BackGrid)
test_utils.create_constraint( test_utils.create_constraint(
self.server, "acceptance_test_db", self.server, self.test_db,
"<h1>X", self.test_table_name,
"unique", "<h1 onmouseover='console.log(2);'>Y" "unique", "<h1 onmouseover='console.log(2);'>Y"
) )
@ -67,24 +57,15 @@ class CheckForXssFeatureTest(BaseFeatureTest):
def after(self): def after(self):
self.page.remove_server(self.server) self.page.remove_server(self.server)
connection = test_utils.get_db_connection(
self.server['db'],
self.server['username'],
self.server['db_password'],
self.server['host'],
self.server['port'],
self.server['sslmode']
)
test_utils.drop_database(connection, "acceptance_test_db")
def _tables_node_expandable(self): def _tables_node_expandable(self):
self.page.toggle_open_server(self.server['name']) self.page.toggle_open_server(self.server['name'])
self.page.toggle_open_tree_item('Databases') self.page.toggle_open_tree_item('Databases')
self.page.toggle_open_tree_item('acceptance_test_db') self.page.toggle_open_tree_item(self.test_db)
self.page.toggle_open_tree_item('Schemas') self.page.toggle_open_tree_item('Schemas')
self.page.toggle_open_tree_item('public') self.page.toggle_open_tree_item('public')
self.page.toggle_open_tree_item('Tables') self.page.toggle_open_tree_item('Tables')
self.page.select_tree_item("<h1>X") self.page.select_tree_item(self.test_table_name)
def _check_xss_in_browser_tree(self): def _check_xss_in_browser_tree(self):
# Fetch the inner html & check for escaped characters # Fetch the inner html & check for escaped characters

View File

@ -7,7 +7,6 @@
# #
########################################################################## ##########################################################################
from selenium.webdriver import ActionChains
from regression.python_test_utils import test_utils from regression.python_test_utils import test_utils
from regression.feature_utils.base_feature_test import BaseFeatureTest from regression.feature_utils.base_feature_test import BaseFeatureTest

View File

@ -499,6 +499,22 @@ define('tools.querytool', [
}; };
}); });
/* If the screen width is small and we hover over the Explain Options,
* the submenu goes behind the screen on the right side.
* Below logic will make it appear on the left.
*/
$('.dropdown-submenu').on('mouseenter',function() {
var menu = $(this).find('ul.dropdown-menu');
var menupos = $(menu).offset();
if (menupos.left + menu.width() > $(window).width()) {
var newpos = -$(menu).width();
menu.css('left',newpos);
}
}).on('mouseleave', function() {
var menu = $(this).find('ul.dropdown-menu');
menu.css('left','');
});
self.reflectPreferences(); self.reflectPreferences();

View File

@ -115,3 +115,7 @@ class BaseTestGenerator(unittest.TestCase):
@classmethod @classmethod
def setServerInformation(cls, server_information): def setServerInformation(cls, server_information):
cls.server_information = server_information cls.server_information = server_information
@classmethod
def setTestDatabaseName(cls, database_name):
cls.test_db = database_name

View File

@ -10,7 +10,7 @@
import time import time
from selenium.common.exceptions import NoSuchElementException, \ from selenium.common.exceptions import NoSuchElementException, \
WebDriverException WebDriverException, TimeoutException, NoSuchWindowException
from selenium.webdriver import ActionChains from selenium.webdriver import ActionChains
from selenium.webdriver.common.keys import Keys from selenium.webdriver.common.keys import Keys
from selenium.webdriver.support import expected_conditions as EC from selenium.webdriver.support import expected_conditions as EC
@ -27,10 +27,23 @@ class PgadminPage:
self.driver = driver self.driver = driver
self.app_config = app_config self.app_config = app_config
self.timeout = 30 self.timeout = 30
self.app_start_timeout = 60 self.app_start_timeout = 90
def reset_layout(self): def reset_layout(self):
self.click_element(self.find_by_partial_link_text("File")) attempt = 0
while attempt < 4:
try:
self.click_element(self.find_by_partial_link_text("File"))
break
except (TimeoutException, NoSuchWindowException):
self.driver.refresh()
try:
WebDriverWait(self.driver, 3).until(EC.alert_is_present())
self.driver.switch_to_alert().accept()
attempt = attempt + 1
except TimeoutException:
attempt = attempt + 1
self.find_by_partial_link_text("Reset Layout").click() self.find_by_partial_link_text("Reset Layout").click()
self.click_modal('OK') self.click_modal('OK')
self.wait_for_reloading_indicator_to_disappear() self.wait_for_reloading_indicator_to_disappear()

View File

@ -19,6 +19,7 @@ import signal
import sys import sys
import traceback import traceback
import json import json
import random
from selenium import webdriver from selenium import webdriver
from selenium.webdriver.chrome.options import Options from selenium.webdriver.chrome.options import Options
@ -126,7 +127,8 @@ unit_test.runner.TextTestResult.addSuccess = test_utils.add_success
scenarios.apply_scenario = test_utils.apply_scenario scenarios.apply_scenario = test_utils.apply_scenario
def get_suite(module_list, test_server, test_app_client, server_information): def get_suite(module_list, test_server, test_app_client, server_information,
test_db_name):
""" """
This function add the tests to test suite and return modified test suite This function add the tests to test suite and return modified test suite
variable. variable.
@ -156,6 +158,7 @@ def get_suite(module_list, test_server, test_app_client, server_information):
obj.setTestServer(test_server) obj.setTestServer(test_server)
obj.setDriver(driver) obj.setDriver(driver)
obj.setServerInformation(server_information) obj.setServerInformation(server_information)
obj.setTestDatabaseName(test_db_name)
scenario = scenarios.generate_scenarios(obj) scenario = scenarios.generate_scenarios(obj)
pgadmin_suite.addTests(scenario) pgadmin_suite.addTests(scenario)
@ -380,7 +383,6 @@ if __name__ == '__main__':
except Exception as e: except Exception as e:
print(str(e)) print(str(e))
sys.exit(1) sys.exit(1)
# Login the test client # Login the test client
test_utils.login_tester_account(test_client) test_utils.login_tester_account(test_client)
@ -395,13 +397,32 @@ if __name__ == '__main__':
# Create test server # Create test server
server_information = test_utils.create_parent_server_node(server) server_information = test_utils.create_parent_server_node(server)
# Create test database with random number to avoid conflict in
# parallel execution on different platforms. This database will be
# used across all feature tests.
test_db_name = "acceptance_test_db" + \
str(random.randint(10000, 65535))
connection = test_utils.get_db_connection(
server['db'],
server['username'],
server['db_password'],
server['host'],
server['port'],
server['sslmode']
)
# Drop the database if already exists.
test_utils.drop_database(connection, test_db_name)
# Create database
test_utils.create_database(server, test_db_name)
if server['default_binary_paths'] is not None: if server['default_binary_paths'] is not None:
test_utils.set_preference(server['default_binary_paths']) test_utils.set_preference(server['default_binary_paths'])
suite = get_suite(test_module_list, suite = get_suite(test_module_list,
server, server,
test_client, test_client,
server_information) server_information, test_db_name)
tests = unit_test.TextTestRunner(stream=sys.stderr, tests = unit_test.TextTestRunner(stream=sys.stderr,
descriptions=True, descriptions=True,
verbosity=2).run(suite) verbosity=2).run(suite)
@ -418,6 +439,11 @@ if __name__ == '__main__':
if len(failed_cases) > 0: if len(failed_cases) > 0:
failure = True failure = True
# Drop the testing database created initially
if connection:
test_utils.drop_database(connection, test_db_name)
connection.close()
# Delete test server # Delete test server
test_utils.delete_test_server(test_client) test_utils.delete_test_server(test_client)
except SystemExit: except SystemExit: