diff --git a/web/pgadmin/feature_tests/copy_selected_query_results_feature_test.py b/web/pgadmin/feature_tests/copy_selected_query_results_feature_test.py index ab54d28..ffe2867 100644 --- a/web/pgadmin/feature_tests/copy_selected_query_results_feature_test.py +++ b/web/pgadmin/feature_tests/copy_selected_query_results_feature_test.py @@ -8,6 +8,7 @@ ########################################################################## import pyperclip +import random from selenium.webdriver import ActionChains from selenium.webdriver.common.keys import Keys @@ -25,32 +26,29 @@ class CopySelectedQueryResultsFeatureTest(BaseFeatureTest): ("Copy rows, column using button and keyboard shortcut", dict()) ] + test_table_name = "" + 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") + + # 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)) + 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) def runTest(self): self.page.toggle_open_tree_item(self.server['name']) 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.driver.switch_to_frame( self.page.driver.find_element_by_tag_name("iframe")) 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() @@ -203,15 +201,9 @@ class CopySelectedQueryResultsFeatureTest(BaseFeatureTest): self.assertIn('"cool info"', pyperclip.paste()) def after(self): + self.page.close_query_tool() 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") + # screen shots + self._screenshot() diff --git a/web/pgadmin/feature_tests/file_manager_test.py b/web/pgadmin/feature_tests/file_manager_test.py index 9cdce65..503fde8 100644 --- a/web/pgadmin/feature_tests/file_manager_test.py +++ b/web/pgadmin/feature_tests/file_manager_test.py @@ -11,11 +11,11 @@ from __future__ import print_function import os import time import sys + from selenium.webdriver.common.keys import Keys from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.common.by import By 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 @@ -28,15 +28,11 @@ class CheckFileManagerFeatureTest(BaseFeatureTest): ] 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'] - ) - test_utils.drop_database(connection, "acceptance_test_db") - test_utils.create_database(self.server, "acceptance_test_db") + if os.name == 'nt': + self.skipTest("This test is skipped for windows since windows" + " does not allow the less than and greater than " + "syntax while saving the file name") + self.page.add_server(self.server) self.wait = WebDriverWait(self.page.driver, 10) self.XSS_FILE = '/tmp/.sql' @@ -47,14 +43,9 @@ class CheckFileManagerFeatureTest(BaseFeatureTest): def after(self): self.page.close_query_tool('sql', False) 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") + + # screen shots + self._screenshot() def runTest(self): print("Tests to check if File manager is vulnerable to XSS... ", @@ -72,7 +63,7 @@ class CheckFileManagerFeatureTest(BaseFeatureTest): def _navigate_to_query_tool(self): self.page.toggle_open_tree_item(self.server['name']) 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() def _create_new_file(self): @@ -145,20 +136,48 @@ class CheckFileManagerFeatureTest(BaseFeatureTest): # Added time.sleep so that the element to be clicked. time.sleep(0.05) - self.page.find_by_css_selector("#contents th[data-column='0']").click() - # Check for sort Ascending - self.wait.until( - EC.presence_of_element_located(( - By.CSS_SELECTOR, - "#contents th[data-column='0'].tablesorter-headerAsc") - ) - ) + + # intermittently facing issues that on first click it is not + # successful + iteration = 0 + success = False + 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("clicked header to sort Name column in" + " decending order, but it is not successful") + + time.sleep(0.05) # Click and Check for sort Descending - self.page.find_by_css_selector("#contents th[data-column='0']").click() - self.wait.until( - EC.presence_of_element_located(( - By.CSS_SELECTOR, - "#contents th[data-column='0'].tablesorter-headerDesc") - ) - ) + # intermittently facing issues that on first click it is not + # successful + 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.wait.until( + EC.presence_of_element_located(( + By.CSS_SELECTOR, "#contents th[" + "data-column='0'].tablesorter-headerDesc") + )) + success = True + except Exception: + iteration += 1 + + if not success: + raise Exception("clicked header to sort Name column in " + "decending order, but it is not successful") diff --git a/web/pgadmin/feature_tests/pg_datatype_validation_test.py b/web/pgadmin/feature_tests/pg_datatype_validation_test.py index 3e34c17..1876f4f 100644 --- a/web/pgadmin/feature_tests/pg_datatype_validation_test.py +++ b/web/pgadmin/feature_tests/pg_datatype_validation_test.py @@ -10,6 +10,7 @@ import os import json import time + from selenium.common.exceptions import TimeoutException from selenium.webdriver.support.ui import WebDriverWait 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.feature_utils.base_feature_test import BaseFeatureTest - CURRENT_PATH = os.path.dirname(os.path.realpath(__file__)) try: @@ -42,14 +42,14 @@ class PGDataypeFeatureTest(BaseFeatureTest): ] 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'] - ) + self.server['sslmode']) self.timezone = int(test_utils.get_timezone_without_dst(connection)) @@ -66,9 +66,6 @@ class PGDataypeFeatureTest(BaseFeatureTest): else: 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 # For this test case we need to set "Insert bracket pairs?" @@ -76,6 +73,9 @@ class PGDataypeFeatureTest(BaseFeatureTest): # to add matching closing bracket by it self. self._update_preferences() + # close the db connection + connection.close() + def _update_preferences(self): self.page.find_by_id("mnu_file").click() self.page.find_by_id("mnu_preferences").click() @@ -124,6 +124,7 @@ class PGDataypeFeatureTest(BaseFeatureTest): """ self.page.fill_codemirror_area_with(query) self.page.find_by_id("btn-flash").click() + self._clear_query_tool() def runTest(self): @@ -136,31 +137,29 @@ class PGDataypeFeatureTest(BaseFeatureTest): self.page.close_query_tool() def after(self): + 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") + + # screen shots + self._screenshot() def _schema_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('acceptance_test_db') + self.page.toggle_open_tree_item(self.test_db) def _check_datatype(self): # Slick grid does not render all the column if viewport is not enough # wide. So execute test as batch of queries. + # self.page.select_tree_item("feature_test_db") + self.page.select_tree_item(self.test_db) self.page.open_query_tool() self._create_enum_type() 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() + wait = WebDriverWait(self.page.driver, 5) wait.until(EC.presence_of_element_located( diff --git a/web/pgadmin/feature_tests/query_tool_journey_test.py b/web/pgadmin/feature_tests/query_tool_journey_test.py index ec12043..f8e5d5b 100644 --- a/web/pgadmin/feature_tests/query_tool_journey_test.py +++ b/web/pgadmin/feature_tests/query_tool_journey_test.py @@ -8,6 +8,7 @@ ########################################################################## import pyperclip +import random from selenium.webdriver import ActionChains from selenium.webdriver.common.keys import Keys @@ -25,26 +26,20 @@ class QueryToolJourneyTest(BaseFeatureTest): ("Tests the path through the query tool", dict()) ] + test_table_name = "" + 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'] - ) - test_utils.drop_database(connection, "acceptance_test_db") - test_utils.create_database(self.server, "acceptance_test_db") + + self.test_table_name = "test_table" + str(random.randint(1000, 3000)) + 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) def runTest(self): self._navigate_to_query_tool() - 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_columns() @@ -100,11 +95,18 @@ class QueryToolJourneyTest(BaseFeatureTest): .perform() selected_history_entry = self.page.find_by_css_selector( "#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_detail_pane = self.page.find_by_id("query_detail") - self.assertIn("SELECT * FROM test_table ORDER BY value", - selected_history_detail_pane.text) + + query_element = self.page.driver.\ + 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( "//*[@id='query_list']/ul/li[2]") self.page.click_element(newly_selected_history_entry) @@ -119,6 +121,7 @@ class QueryToolJourneyTest(BaseFeatureTest): self.page.fill_codemirror_area_with("SELECT * FROM hats") for _ in range(15): self.page.find_by_id("btn-flash").click() + self.page.wait_for_query_tool_loading_indicator_to_disappear() self.page.click_tab("Query History") @@ -140,6 +143,7 @@ class QueryToolJourneyTest(BaseFeatureTest): self.page.fill_codemirror_area_with("SELECT * FROM hats") for _ in range(15): self.page.find_by_id("btn-flash").click() + self.page.wait_for_query_tool_loading_indicator_to_disappear() self.page.click_tab("History") @@ -167,7 +171,7 @@ class QueryToolJourneyTest(BaseFeatureTest): def _navigate_to_query_tool(self): self.page.toggle_open_tree_item(self.server['name']) 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() def _execute_query(self, query): @@ -181,9 +185,5 @@ class QueryToolJourneyTest(BaseFeatureTest): self.page.close_query_tool() 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") + # screen shots + self._screenshot() diff --git a/web/pgadmin/feature_tests/query_tool_tests.py b/web/pgadmin/feature_tests/query_tool_tests.py index 226b323..940e730 100644 --- a/web/pgadmin/feature_tests/query_tool_tests.py +++ b/web/pgadmin/feature_tests/query_tool_tests.py @@ -8,7 +8,6 @@ ########################################################################## from __future__ import print_function -import time import sys from selenium.common.exceptions import StaleElementReferenceException @@ -32,20 +31,11 @@ class QueryToolFeatureTest(BaseFeatureTest): ] 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.add_server(self.server) self._locate_database_tree_node() self.page.open_query_tool() + self.page.wait_for_spinner_to_disappear() self._reset_options() def runTest(self): @@ -116,15 +106,9 @@ class QueryToolFeatureTest(BaseFeatureTest): def after(self): 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") + + # screen shots + self._screenshot() def _reset_options(self): # this will set focus to correct iframe. @@ -135,6 +119,10 @@ class QueryToolFeatureTest(BaseFeatureTest): ActionChains(self.driver).move_to_element( query_op.find_element_by_xpath( "//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. for op in ('explain-verbose', 'explain-costs', @@ -156,7 +144,7 @@ class QueryToolFeatureTest(BaseFeatureTest): 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('acceptance_test_db') + self.page.toggle_open_tree_item(self.test_db) def _clear_query_tool(self): self.page.click_element( @@ -187,8 +175,6 @@ SELECT generate_series(1, {}) as id1, 'dummy' as id2""".format( 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( (By.XPATH, '//span[@data-row="0" and text()="1"]')) @@ -210,8 +196,6 @@ SELECT generate_series(1, {}) as id1, 'dummy' as id2""".format( file=sys.stderr, end="") 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( (By.XPATH, '//span[@data-row="0" and text()="1"]')) @@ -230,7 +214,7 @@ SELECT generate_series(1, {}) as id1, 'dummy' as id2""".format( file=sys.stderr, end="") 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( (By.XPATH, @@ -275,6 +259,11 @@ SELECT generate_series(1, 1000) as id order by id desc""" query_op.find_element_by_xpath( "//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-costs").click() @@ -310,6 +299,11 @@ SELECT generate_series(1, 1000) as id order by id desc""" query_op.find_element_by_xpath( "//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-timing").click() @@ -349,6 +343,7 @@ CREATE TABLE public.{}();""".format(table_name) self.page.find_by_id("btn-auto-commit").click() self.page.find_by_id("btn-flash").click() + self.page.wait_for_query_tool_loading_indicator_to_disappear() self.page.click_tab('Messages') self.page.find_by_xpath( @@ -364,6 +359,7 @@ CREATE TABLE public.{}();""".format(table_name) ROLLBACK;""" self.page.fill_codemirror_area_with(query) self.page.find_by_id("btn-flash").click() + self.page.wait_for_query_tool_loading_indicator_to_disappear() self.page.click_tab('Messages') self.page.find_by_xpath( @@ -380,6 +376,7 @@ 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_id("btn-flash").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( @@ -448,6 +445,7 @@ CREATE TABLE public.{}();""".format(table_name) ROLLBACK;""" self.page.fill_codemirror_area_with(query) self.page.find_by_id("btn-flash").click() + self.page.wait_for_query_tool_loading_indicator_to_disappear() self.page.click_tab('Messages') self.page.find_by_xpath( @@ -465,6 +463,7 @@ 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_id("btn-flash").click() + self.page.click_tab('Data Output') self.page.wait_for_query_tool_loading_indicator_to_disappear() @@ -496,6 +495,7 @@ END;""" self.page.find_by_id("btn-auto-commit").click() self.page.find_by_id("btn-flash").click() + self.page.wait_for_query_tool_loading_indicator_to_disappear() self._clear_query_tool() @@ -511,6 +511,7 @@ CREATE TABLE public.{}();""".format(table_name) self.page.fill_codemirror_area_with(query) self.page.find_by_id("btn-flash").click() + self.page.wait_for_query_tool_loading_indicator_to_disappear() self.page.click_tab('Messages') self.page.find_by_xpath( @@ -528,6 +529,7 @@ CREATE TABLE public.{}();""".format(table_name) SELECT 1/0;""" self.page.fill_codemirror_area_with(query) self.page.find_by_id("btn-flash").click() + self.page.wait_for_query_tool_loading_indicator_to_disappear() self.page.click_tab('Messages') self.page.find_by_xpath( @@ -546,6 +548,7 @@ END;""" self.page.fill_codemirror_area_with(query) self.page.find_by_id("btn-flash").click() + self.page.wait_for_query_tool_loading_indicator_to_disappear() self.page.click_tab('Messages') self.page.find_by_xpath( @@ -564,6 +567,7 @@ 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_id("btn-flash").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( @@ -583,6 +587,7 @@ SELECT relname FROM pg_class -- 4. Cancel long running query execution. END; SELECT 1, pg_sleep(300)""" + self.page.fill_codemirror_area_with(query) self.page.find_by_id("btn-query-dropdown").click() @@ -614,6 +619,7 @@ SELECT 1, pg_sleep(300)""" auto_commit_btn.click() self.page.find_by_id("btn-flash").click() + self.page.find_by_xpath("//*[@id='fetching_data']") self.page.find_by_id("btn-cancel-query").click() self.page.wait_for_query_tool_loading_indicator_to_disappear() @@ -640,6 +646,7 @@ SELECT 1, pg_sleep(300)""" print("\n\tListen on an event... ", file=sys.stderr, end="") self.page.fill_codemirror_area_with("LISTEN foo;") self.page.find_by_id("btn-flash").click() + self.page.wait_for_query_tool_loading_indicator_to_disappear() self.page.click_tab('Messages') @@ -652,6 +659,7 @@ SELECT 1, pg_sleep(300)""" print("\tNotify event without data... ", file=sys.stderr, end="") self.page.fill_codemirror_area_with("NOTIFY foo;") self.page.find_by_id("btn-flash").click() + self.page.wait_for_query_tool_loading_indicator_to_disappear() self.page.click_tab('Notifications') wait.until(EC.text_to_be_present_in_element( @@ -665,12 +673,12 @@ SELECT 1, pg_sleep(300)""" self.page.fill_codemirror_area_with("SELECT pg_notify('foo', " "'Hello')") self.page.find_by_id("btn-flash").click() + self.page.wait_for_query_tool_loading_indicator_to_disappear() self.page.click_tab('Notifications') wait.until(WaitForAnyElementWithText( (By.CSS_SELECTOR, 'td.payload'), "Hello")) print("OK.", file=sys.stderr) - self._clear_query_tool() else: print("Skipped.", file=sys.stderr) diff --git a/web/pgadmin/feature_tests/table_ddl_feature_test.py b/web/pgadmin/feature_tests/table_ddl_feature_test.py index 1876001..4a48559 100644 --- a/web/pgadmin/feature_tests/table_ddl_feature_test.py +++ b/web/pgadmin/feature_tests/table_ddl_feature_test.py @@ -7,6 +7,8 @@ # ########################################################################## +import random + from regression.feature_utils.base_feature_test import BaseFeatureTest from regression.python_test_utils import test_utils @@ -18,46 +20,34 @@ class TableDdlFeatureTest(BaseFeatureTest): ("Test table DDL generation", dict()) ] + test_table_name = "" + 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.add_server(self.server) def runTest(self): - test_utils.create_table( - self.server, "acceptance_test_db", "test_table") + + self.test_table_name = "test_table" + str(random.randint(1000, 3000)) + + 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_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('public') 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.find_by_xpath( - "//*[contains(@class,'CodeMirror-lines') and " - "contains(.,'CREATE TABLE public.test_table')]") + "//*[contains(@class,'CodeMirror-lines') and contains(" + ".,'CREATE TABLE public.%s')]" % self.test_table_name) def after(self): 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") + + # screen shots + self._screenshot() diff --git a/web/pgadmin/feature_tests/view_data_dml_queries.py b/web/pgadmin/feature_tests/view_data_dml_queries.py index f5dc659..f29c9e3 100644 --- a/web/pgadmin/feature_tests/view_data_dml_queries.py +++ b/web/pgadmin/feature_tests/view_data_dml_queries.py @@ -10,6 +10,7 @@ import json import os import time + from selenium.webdriver import ActionChains from regression.python_test_utils import test_utils 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" ) - 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 for k, v in {1: 'id', 2: '"ID"'}.items(): test_utils.create_table_with_query( self.server, - "acceptance_test_db", + self.test_db, CheckForViewDataTest.defaults_query.format(k, v)) # Initialize an instance of WebDriverWait with timeout of 3 seconds self.wait = WebDriverWait(self.driver, 3) + # close the db connection + connection.close() + def runTest(self): self.page.wait_for_spinner_to_disappear() self.page.add_server(self.server) @@ -129,15 +122,9 @@ CREATE TABLE public.defaults_{0} def after(self): 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") + + # screen shots + self._screenshot() @staticmethod def _get_cell_xpath(cell, row): @@ -227,7 +214,7 @@ CREATE TABLE public.defaults_{0} 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('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('public') self.page.toggle_open_tree_item('Tables') diff --git a/web/pgadmin/feature_tests/xss_checks_panels_and_query_tool_test.py b/web/pgadmin/feature_tests/xss_checks_panels_and_query_tool_test.py index 4dc082c..284279d 100644 --- a/web/pgadmin/feature_tests/xss_checks_panels_and_query_tool_test.py +++ b/web/pgadmin/feature_tests/xss_checks_panels_and_query_tool_test.py @@ -29,26 +29,16 @@ class CheckForXssFeatureTest(BaseFeatureTest): scenarios = [ ("Test XSS check for panels and query tool", dict()) ] + test_table_name = "

X" 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( - self.server, "acceptance_test_db", "

X" + self.server, self.test_db, self.test_table_name ) - # This is needed to test dependents tab (eg: BackGrid) test_utils.create_constraint( - self.server, "acceptance_test_db", - "

X", + self.server, self.test_db, + self.test_table_name, "unique", "

Y" ) @@ -67,24 +57,18 @@ class CheckForXssFeatureTest(BaseFeatureTest): def after(self): 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") + + # screen shots + self._screenshot() def _tables_node_expandable(self): self.page.toggle_open_server(self.server['name']) 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('public') self.page.toggle_open_tree_item('Tables') - self.page.select_tree_item("

X") + self.page.select_tree_item(self.test_table_name) def _check_xss_in_browser_tree(self): # Fetch the inner html & check for escaped characters diff --git a/web/pgadmin/feature_tests/xss_checks_pgadmin_debugger_test.py b/web/pgadmin/feature_tests/xss_checks_pgadmin_debugger_test.py index 17ce615..1ec2cc4 100644 --- a/web/pgadmin/feature_tests/xss_checks_pgadmin_debugger_test.py +++ b/web/pgadmin/feature_tests/xss_checks_pgadmin_debugger_test.py @@ -47,6 +47,9 @@ class CheckDebuggerForXssFeatureTest(BaseFeatureTest): test_utils.drop_debug_function(self.server, "postgres", "a_test_function") + # screen shots + self._screenshot() + def _function_node_expandable(self): self.page.toggle_open_server(self.server['name']) self.page.toggle_open_tree_item('Databases') diff --git a/web/pgadmin/feature_tests/xss_checks_roles_control_test.py b/web/pgadmin/feature_tests/xss_checks_roles_control_test.py index 21a2027..eca4684 100644 --- a/web/pgadmin/feature_tests/xss_checks_roles_control_test.py +++ b/web/pgadmin/feature_tests/xss_checks_roles_control_test.py @@ -7,7 +7,6 @@ # ########################################################################## -from selenium.webdriver import ActionChains from regression.python_test_utils import test_utils from regression.feature_utils.base_feature_test import BaseFeatureTest @@ -33,6 +32,8 @@ class CheckRoleMembershipControlFeatureTest(BaseFeatureTest): "

test

") def runTest(self): + print("TestExecution-CheckRoleMembershipControlFeatureTest and name o" + "f test db is: %s " % self.test_db) self.page.wait_for_spinner_to_disappear() self.page.add_server(self.server) self._role_node_expandable() @@ -45,6 +46,9 @@ class CheckRoleMembershipControlFeatureTest(BaseFeatureTest): test_utils.drop_role(self.server, "postgres", "

test

") + # screen shots + self._screenshot() + def _role_node_expandable(self): self.page.toggle_open_server(self.server['name']) self.page.toggle_open_tree_item('Login/Group Roles') diff --git a/web/pgadmin/tools/sqleditor/static/js/sqleditor.js b/web/pgadmin/tools/sqleditor/static/js/sqleditor.js index 1316c7b..b390375 100644 --- a/web/pgadmin/tools/sqleditor/static/js/sqleditor.js +++ b/web/pgadmin/tools/sqleditor/static/js/sqleditor.js @@ -499,6 +499,22 @@ define('tools.querytool', [ }; }); + /* If the screen width is small and if we hover over the Explain Options, + * the submenu goes behind the screen on the right side. This code 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(); diff --git a/web/pgadmin/utils/route.py b/web/pgadmin/utils/route.py index f784e53..138f9ea 100644 --- a/web/pgadmin/utils/route.py +++ b/web/pgadmin/utils/route.py @@ -115,3 +115,7 @@ class BaseTestGenerator(unittest.TestCase): @classmethod def setServerInformation(cls, server_information): cls.server_information = server_information + + @classmethod + def setTestDbName(cls, db): + cls.test_db = db diff --git a/web/regression/feature_utils/pgadmin_page.py b/web/regression/feature_utils/pgadmin_page.py index aacb925..4013ef9 100644 --- a/web/regression/feature_utils/pgadmin_page.py +++ b/web/regression/feature_utils/pgadmin_page.py @@ -10,7 +10,7 @@ import time from selenium.common.exceptions import NoSuchElementException, \ - WebDriverException + WebDriverException, TimeoutException, NoSuchWindowException from selenium.webdriver import ActionChains from selenium.webdriver.common.keys import Keys from selenium.webdriver.support import expected_conditions as EC @@ -27,10 +27,23 @@ class PgadminPage: self.driver = driver self.app_config = app_config self.timeout = 30 - self.app_start_timeout = 60 + self.app_start_timeout = 90 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.click_modal('OK') self.wait_for_reloading_indicator_to_disappear() diff --git a/web/regression/runtests.py b/web/regression/runtests.py index 4cd4553..fce7e37 100644 --- a/web/regression/runtests.py +++ b/web/regression/runtests.py @@ -19,6 +19,7 @@ import signal import sys import traceback import json +import random from selenium import webdriver 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 -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 variable. @@ -156,6 +158,7 @@ def get_suite(module_list, test_server, test_app_client, server_information): obj.setTestServer(test_server) obj.setDriver(driver) obj.setServerInformation(server_information) + obj.setTestDbName(test_db_name) scenario = scenarios.generate_scenarios(obj) pgadmin_suite.addTests(scenario) @@ -380,7 +383,6 @@ if __name__ == '__main__': except Exception as e: print(str(e)) sys.exit(1) - # Login the test client test_utils.login_tester_account(test_client) @@ -395,13 +397,30 @@ if __name__ == '__main__': # Create test server server_information = test_utils.create_parent_server_node(server) + # create test db with random number to avoid conflict in + # parallel execution on different platforms. This db 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'] + ) + + test_utils.drop_database(connection, test_db_name) + test_utils.create_database(server, test_db_name) + if server['default_binary_paths'] is not None: test_utils.set_preference(server['default_binary_paths']) suite = get_suite(test_module_list, server, test_client, - server_information) + server_information, test_db_name) tests = unit_test.TextTestRunner(stream=sys.stderr, descriptions=True, verbosity=2).run(suite) @@ -418,6 +437,11 @@ if __name__ == '__main__': if len(failed_cases) > 0: failure = True + # drop the testing database created initially + if connection: + test_utils.drop_database(connection, test_db_name) + connection.close() + # Delete test server test_utils.delete_test_server(test_client) except SystemExit: