diff --git a/web/pgadmin/feature_tests/connect_to_server_feature_test.py b/web/pgadmin/feature_tests/connect_to_server_feature_test.py deleted file mode 100644 index 97e96f27e..000000000 --- a/web/pgadmin/feature_tests/connect_to_server_feature_test.py +++ /dev/null @@ -1,84 +0,0 @@ -########################################################################## -# -# pgAdmin 4 - PostgreSQL Tools -# -# Copyright (C) 2013 - 2017, The pgAdmin Development Team -# This software is released under the PostgreSQL Licence -# -########################################################################## - -import time -from selenium.webdriver import ActionChains - -import config as app_config -from regression.feature_utils.base_feature_test import BaseFeatureTest -from regression.python_test_utils import test_utils - - -class ConnectsToServerFeatureTest(BaseFeatureTest): - """ - Tests that a database connection can be created from the UI - """ - scenarios = [ - ("Test database connection", dict()) - ] - - 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", "test_table") - - def runTest(self): - """This function tests that a database connection can be created from - the UI""" - self.assertEqual(app_config.APP_NAME, self.page.driver.title) - self.page.wait_for_spinner_to_disappear() - - self._connects_to_server() - self._tables_node_expandable() - - 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") - - def _connects_to_server(self): - self.page.find_by_xpath("//*[@class='aciTreeText' and .='Servers']").click() - time.sleep(2) - 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("Create")) \ - .perform() - self.page.find_by_partial_link_text("Server...").click() - - server_config = self.server - self.page.fill_input_by_field_name("name", server_config['name']) - self.page.find_by_partial_link_text("Connection").click() - self.page.fill_input_by_field_name("host", server_config['host']) - self.page.fill_input_by_field_name("port", server_config['port']) - self.page.fill_input_by_field_name("username", server_config['username']) - self.page.fill_input_by_field_name("password", server_config['db_password']) - self.page.find_by_xpath("//button[contains(.,'Save')]").click() - - 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') - # wait until all database dependant modules/js are loaded. - time.sleep(5) - self.page.toggle_open_tree_item('Schemas') - self.page.toggle_open_tree_item('public') - self.page.toggle_open_tree_item('Tables') - self.page.toggle_open_tree_item('test_table') 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 1809d45ea..d01bf662f 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,7 +8,6 @@ ########################################################################## import pyperclip -import time from selenium.webdriver import ActionChains from selenium.webdriver.common.keys import Keys @@ -42,16 +41,16 @@ class CopySelectedQueryResultsFeatureTest(BaseFeatureTest): 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') - time.sleep(5) - self.page.find_by_partial_link_text("Tools").click() - self.page.find_by_partial_link_text("Query Tool").click() - self.page.click_tab('Query -') - time.sleep(5) - ActionChains(self.page.driver).send_keys("SELECT * FROM test_table ORDER BY some_column").perform() - self.page.driver.switch_to_frame(self.page.driver.find_element_by_tag_name("iframe")) + 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") + self.page.find_by_id("btn-flash").click() - time.sleep(5) self._copies_rows() self._copies_columns() self._copies_row_using_keyboard_shortcut() diff --git a/web/pgadmin/feature_tests/pg_datatype_validation_test.py b/web/pgadmin/feature_tests/pg_datatype_validation_test.py index f700aab61..75993a491 100644 --- a/web/pgadmin/feature_tests/pg_datatype_validation_test.py +++ b/web/pgadmin/feature_tests/pg_datatype_validation_test.py @@ -6,8 +6,7 @@ # This software is released under the PostgreSQL Licence # ########################################################################## -import time -from selenium.webdriver import ActionChains + from selenium.common.exceptions import TimeoutException from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC @@ -38,7 +37,7 @@ class PGDataypeFeatureTest(BaseFeatureTest): def runTest(self): self.page.wait_for_spinner_to_disappear() - self._connects_to_server() + self.page.add_server(self.server) self._schema_node_expandable() # Check data types @@ -55,31 +54,6 @@ class PGDataypeFeatureTest(BaseFeatureTest): self.server['sslmode']) test_utils.drop_database(connection, "acceptance_test_db") - def _connects_to_server(self): - self.page.find_by_xpath( - "//*[@class='aciTreeText' and .='Servers']" - ).click() - time.sleep(2) - 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("Create") - ).perform() - self.page.find_by_partial_link_text("Server...").click() - - server_config = self.server - self.page.fill_input_by_field_name("name", server_config['name']) - self.page.find_by_partial_link_text("Connection").click() - self.page.fill_input_by_field_name("host", server_config['host']) - self.page.fill_input_by_field_name("port", server_config['port']) - self.page.fill_input_by_field_name( - "username", server_config['username'] - ) - self.page.fill_input_by_field_name( - "password", server_config['db_password'] - ) - self.page.find_by_xpath("//button[contains(.,'Save')]").click() - def _schema_node_expandable(self): self.page.toggle_open_tree_item(self.server['name']) self.page.toggle_open_tree_item('Databases') @@ -136,11 +110,9 @@ class PGDataypeFeatureTest(BaseFeatureTest): @staticmethod def check_result(source_code, string_to_find): - if source_code.find(string_to_find) == -1: - assert False, "{0} does not match with {1}".format( + assert source_code.find(string_to_find) != -1,\ + "{0} does not match with {1}".format( source_code, string_to_find ) - else: - assert True diff --git a/web/pgadmin/feature_tests/query_tool_journey_test.py b/web/pgadmin/feature_tests/query_tool_journey_test.py index e7ccb22c7..87514b162 100644 --- a/web/pgadmin/feature_tests/query_tool_journey_test.py +++ b/web/pgadmin/feature_tests/query_tool_journey_test.py @@ -8,7 +8,6 @@ ########################################################################## import pyperclip -import time from selenium.webdriver import ActionChains from selenium.webdriver.common.keys import Keys @@ -39,7 +38,10 @@ class QueryToolJourneyTest(BaseFeatureTest): def runTest(self): self._navigate_to_query_tool() - self._execute_query("SELECT * FROM test_table ORDER BY value") + + self._execute_query( + "SELECT * FROM test_table ORDER BY value" + ) self._test_copies_rows() self._test_copies_columns() @@ -47,7 +49,6 @@ class QueryToolJourneyTest(BaseFeatureTest): def _test_copies_rows(self): pyperclip.copy("old clipboard contents") - time.sleep(5) 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() @@ -95,8 +96,11 @@ class QueryToolJourneyTest(BaseFeatureTest): self.__clear_query_tool() self.page.click_element(editor_input) + + self.page.fill_codemirror_area_with("SELECT * FROM hats") for _ in range(15): - self._execute_query("SELECT * FROM hats") + self.page.find_by_id("btn-flash").click() + self.page.wait_for_query_tool_loading_indicator_to_disappear() self.page.click_tab("Query History") @@ -113,8 +117,10 @@ class QueryToolJourneyTest(BaseFeatureTest): self.__clear_query_tool() self.page.click_element(editor_input) + self.page.fill_codemirror_area_with("SELECT * FROM hats") for _ in range(15): - self._execute_query("SELECT * FROM hats") + self.page.find_by_id("btn-flash").click() + self.page.wait_for_query_tool_loading_indicator_to_disappear() self.page.click_tab("History") query_we_need_to_scroll_to = self.page.find_by_xpath( @@ -143,12 +149,9 @@ class QueryToolJourneyTest(BaseFeatureTest): self.page.toggle_open_tree_item('Databases') self.page.toggle_open_tree_item('acceptance_test_db') self.page.open_query_tool() - time.sleep(5) def _execute_query(self, query): - ActionChains(self.page.driver).send_keys(query).perform() - self.page.driver.switch_to.default_content() - self.page.driver.switch_to_frame(self.page.driver.find_element_by_tag_name("iframe")) + self.page.fill_codemirror_area_with(query) self.page.find_by_id("btn-flash").click() def _assert_clickable(self, element): diff --git a/web/pgadmin/feature_tests/query_tool_tests.py b/web/pgadmin/feature_tests/query_tool_tests.py index 212885f02..e2adb6e73 100644 --- a/web/pgadmin/feature_tests/query_tool_tests.py +++ b/web/pgadmin/feature_tests/query_tool_tests.py @@ -38,68 +38,28 @@ class QueryToolFeatureTest(BaseFeatureTest): 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._connects_to_server() + self.page.add_server(self.server) self._locate_database_tree_node() self.page.open_query_tool() def runTest(self): # on demand result set on scrolling. - print("\nOn demand result set on scrolling... ", + print("\nOn demand query result... ", file=sys.stderr, end="") self._on_demand_result() - print("OK.", - file=sys.stderr) self._clear_query_tool() - # on demand result set on grid select all. - print("On demand result set on grid select all... ", + # explain query with verbose and cost + print("Explain query with verbose and cost... ", file=sys.stderr, end="") - self._on_demand_result_select_all_grid() - print("OK.", - file=sys.stderr) + self._query_tool_explain_with_verbose_and_cost() + print("OK.", file=sys.stderr) self._clear_query_tool() - # on demand result set on column select all. - print("On demand result set on column select all... ", + # explain analyze query with buffers and timing + print("Explain analyze query with buffers and timing... ", file=sys.stderr, end="") - self._on_demand_result_select_all_column() - print("OK.", - file=sys.stderr) - self._clear_query_tool() - - # explain query - print("Explain query... ", file=sys.stderr, end="") - self._query_tool_explain() - print("OK.", file=sys.stderr) - self._clear_query_tool() - - # explain query with verbose - print("Explain query with verbose... ", file=sys.stderr, end="") - self._query_tool_explain_verbose() - print("OK.", file=sys.stderr) - self._clear_query_tool() - - # explain query with costs - print("Explain query with costs... ", file=sys.stderr, end="") - self._query_tool_explain_cost() - print("OK.", file=sys.stderr) - self._clear_query_tool() - - # explain analyze query - print("Explain analyze query... ", file=sys.stderr, end="") - self._query_tool_explain_analyze() - print("OK.", file=sys.stderr) - self._clear_query_tool() - - # explain analyze query with buffers - print("Explain analyze query with buffers... ", file=sys.stderr, end="") - self._query_tool_explain_analyze_buffers() - print("OK.", file=sys.stderr) - self._clear_query_tool() - - # explain analyze query with timing - print("Explain analyze query with timing... ", file=sys.stderr, end="") - self._query_tool_explain_analyze_timing() + self._query_tool_explain_analyze_with_buffers_and_timing() print("OK.", file=sys.stderr) self._clear_query_tool() @@ -137,32 +97,6 @@ class QueryToolFeatureTest(BaseFeatureTest): self.server['sslmode']) test_utils.drop_database(connection, "acceptance_test_db") - def _connects_to_server(self): - self.page.find_by_xpath( - "//*[@class='aciTreeText' and .='Servers']").click() - time.sleep(2) - 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("Create"))\ - .perform() - self.page.find_by_partial_link_text("Server...").click() - - server_config = self.server - self.page.fill_input_by_field_name("name", server_config['name']) - self.page.find_by_partial_link_text("Connection").click() - self.page.fill_input_by_field_name("host", server_config['host']) - self.page.fill_input_by_field_name("port", server_config['port']) - self.page.fill_input_by_field_name( - "username", - server_config['username'] - ) - self.page.fill_input_by_field_name( - "password", - server_config['db_password'] - ) - self.page.find_by_xpath("//button[contains(.,'Save')]").click() - def _locate_database_tree_node(self): self.page.toggle_open_tree_item(self.server['name']) self.page.toggle_open_tree_item('Databases') @@ -182,169 +116,105 @@ class QueryToolFeatureTest(BaseFeatureTest): def _on_demand_result(self): ON_DEMAND_CHUNKS = 2 - query = """-- On demand query result on scroll -SELECT generate_series(1, {}) as id""".format( + row_id_to_find = config.ON_DEMAND_RECORD_COUNT * ON_DEMAND_CHUNKS + + query = """-- On demand query result on scroll, grid select all, column select all +SELECT generate_series(1, {}) as id1, 'dummy' as id2""".format( config.ON_DEMAND_RECORD_COUNT * ON_DEMAND_CHUNKS) + print("\nOn demand result set on scrolling... ", + file=sys.stderr, end="") wait = WebDriverWait(self.page.driver, 10) - time.sleep(1) 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.wait_for_query_tool_loading_indicator_to_disappear() - canvas = wait.until(EC.presence_of_element_located( - (By.CSS_SELECTOR, "#datagrid .slick-viewport .grid-canvas"))) + wait.until(EC.presence_of_element_located( + (By.XPATH, + '//span[@data-row="0" and text()="1"]')) + ) # 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());" ) - # wait for ajax to complete. - time.sleep(1) - # again 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 = wait.until(EC.presence_of_element_located( + (By.CSS_SELECTOR, "#datagrid .slick-viewport .grid-canvas"))) - row_id_to_find = config.ON_DEMAND_RECORD_COUNT * ON_DEMAND_CHUNKS - - canvas.find_element_by_xpath( - '//span[text()="{}"]'.format(row_id_to_find) - ) - - def _on_demand_result_select_all_grid(self): - ON_DEMAND_CHUNKS = 3 - query = """-- On demand query result on grid select all -SELECT generate_series(1, {}) as id""".format( - config.ON_DEMAND_RECORD_COUNT * ON_DEMAND_CHUNKS) - - wait = WebDriverWait(self.page.driver, 10) - - self.page.fill_codemirror_area_with(query) + self._check_ondemand_result(row_id_to_find, canvas) + print("OK.", file=sys.stderr) + print("On demand result set on grid select all... ", + 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, + '//span[@data-row="0" and text()="1"]')) + ) wait.until(EC.presence_of_element_located( (By.CSS_SELECTOR, ".slick-header-column"))).click() - # wait for until all records are fetched and selected. - time.sleep(1) - # 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 = wait.until(EC.presence_of_element_located( - (By.CSS_SELECTOR, "#datagrid .slick-viewport .grid-canvas")) - ) + (By.CSS_SELECTOR, "#datagrid .slick-viewport .grid-canvas"))) - row_id_to_find = config.ON_DEMAND_RECORD_COUNT * ON_DEMAND_CHUNKS - - canvas.find_element_by_xpath( - '//span[text()="{}"]'.format(row_id_to_find) - ) - - def _on_demand_result_select_all_column(self): - ON_DEMAND_CHUNKS = 4 - query = """-- On demand query result on column select all -SELECT generate_series(1, {}) as id1, 'dummy' as id2""".format( - config.ON_DEMAND_RECORD_COUNT * ON_DEMAND_CHUNKS) - - wait = WebDriverWait(self.page.driver, 10) - - self.page.fill_codemirror_area_with(query) + self._check_ondemand_result(row_id_to_find, canvas) + print("OK.", file=sys.stderr) + print("On demand result set on column select all... ", + 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, + '//span[@data-row="0" and text()="1"]')) + ) # 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() - # wait for until all records are fetched and selected. - time.sleep(1) - # scroll to bottom to bring last row of next chunk in - # viewport. + 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) + print("OK.", file=sys.stderr) + + def _check_ondemand_result(self, row_id_to_find, canvas): + # 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 = wait.until(EC.presence_of_element_located( - (By.CSS_SELECTOR, "#datagrid .slick-viewport .grid-canvas")) - ) - - row_id_to_find = config.ON_DEMAND_RECORD_COUNT * ON_DEMAND_CHUNKS - canvas.find_element_by_xpath( '//span[text()="{}"]'.format(row_id_to_find) ) - def _query_tool_explain(self): - query = """-- Explain query + 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) - self.page.find_by_id("btn-query-dropdown").click() - self.page.find_by_id("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")) - ) - # Search for Plan word in result - canvas.find_element_by_xpath("//*[contains(string(),'Plan')]") - - def _query_tool_explain_verbose(self): - query = """-- Explain query with verbose -SELECT generate_series(1, 1000) as id order by id desc""" - - wait = WebDriverWait(self.page.driver, 10) self.page.fill_codemirror_area_with(query) query_op = self.page.find_by_id("btn-query-dropdown") query_op.click() ActionChains(self.driver).move_to_element( query_op.find_element_by_xpath( "//li[contains(.,'Explain Options')]")).perform() + self.page.find_by_id("btn-explain-verbose").click() - self.page.find_by_id("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")) - ) - # Search for 'Output' word in result - canvas.find_element_by_xpath("//*[contains(string(), 'Output')]") - - def _query_tool_explain_cost(self): - query = """-- Explain query with costs -SELECT generate_series(1, 1000) as id order by id desc""" - - wait = WebDriverWait(self.page.driver, 10) - - self.page.fill_codemirror_area_with(query) - query_op = self.page.find_by_id("btn-query-dropdown") - query_op.click() - - ActionChains(self.driver).move_to_element( - query_op.find_element_by_xpath( - "//li[contains(.,'Explain Options')]")).perform() self.page.find_by_id("btn-explain-costs").click() @@ -357,32 +227,15 @@ SELECT generate_series(1, 1000) as id order by id desc""" canvas = wait.until(EC.presence_of_element_located( (By.CSS_SELECTOR, "#datagrid .slick-viewport .grid-canvas")) ) - # Search for 'Total Cost word in result + + # Search for 'Output' word in result (verbose option) + canvas.find_element_by_xpath("//*[contains(string(), 'Output')]") + + # Search for 'Total Cost' word in result (cost option) canvas.find_element_by_xpath("//*[contains(string(),'Total Cost')]") - def _query_tool_explain_analyze(self): - query = """-- Explain analyze query -SELECT generate_series(1, 1000) as id order by id desc""" - - wait = WebDriverWait(self.page.driver, 10) - - self.page.fill_codemirror_area_with(query) - - self.page.find_by_id("btn-query-dropdown").click() - self.page.find_by_id("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 Actual Rows word in result - canvas.find_element_by_xpath("//*[contains(string(),'Actual Rows')]") - - def _query_tool_explain_analyze_buffers(self): - query = """-- Explain analyze query with buffers + def _query_tool_explain_analyze_with_buffers_and_timing(self): + 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) @@ -398,32 +251,6 @@ SELECT generate_series(1, 1000) as id order by id desc""" self.page.find_by_id("btn-explain-buffers").click() - self.page.find_by_id("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 - canvas.find_element_by_xpath("//*[contains(string(), 'Shared Read Blocks')]") - - def _query_tool_explain_analyze_timing(self): - query = """-- Explain analyze query with 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) - query_op = self.page.find_by_id("btn-query-dropdown") - query_op.click() - - ActionChains(self.driver).move_to_element( - query_op.find_element_by_xpath( - "//li[contains(.,'Explain Options')]")).perform() - self.page.find_by_id("btn-explain-timing").click() self.page.find_by_id("btn-explain-analyze").click() @@ -435,8 +262,15 @@ SELECT generate_series(1, 1000) as id order by id desc""" canvas = wait.until(EC.presence_of_element_located( (By.CSS_SELECTOR, "#datagrid .slick-viewport .grid-canvas")) ) - # Search for 'Actual Total Time' word in result - canvas.find_element_by_xpath("//*[contains(string(), 'Actual Total Time')]") + # Search for 'Shared Read Blocks' word in result (buffers option) + canvas.find_element_by_xpath( + "//*[contains(string(), 'Shared Read Blocks')]" + ) + + # Search for 'Actual Total Time' word in result (timing option) + canvas.find_element_by_xpath( + "//*[contains(string(), 'Actual Total Time')]" + ) def _query_tool_auto_commit_disabled(self): table_name = 'query_tool_auto_commit_disabled_table' @@ -451,23 +285,12 @@ CREATE TABLE public.{}();""".format(table_name) self.page.find_by_id("btn-query-dropdown").click() - auto_commit_btn = self.page.find_by_id("btn-auto-commit") - - auto_commit_check = auto_commit_btn.find_element_by_tag_name("i") - - # if auto commit is enabled then 'i' element will - # have 'auto-commit fa fa-check' classes - # if auto commit is disabled then 'i' element will - # have 'auto-commit fa fa-check visibility-hidden' classes - - if 'auto-commit fa fa-check' == str(auto_commit_check.get_attribute( - 'class')): - auto_commit_btn.click() + 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.driver.find_element_by_xpath( + self.page.find_by_xpath( '//div[contains(@class, "sql-editor-message") and contains(string(), "CREATE TABLE")]' ) @@ -481,7 +304,7 @@ ROLLBACK;""" self.page.find_by_id("btn-flash").click() self.page.wait_for_query_tool_loading_indicator_to_disappear() self.page.click_tab('Messages') - self.driver.find_element_by_xpath( + self.page.find_by_xpath( '//div[contains(@class, "sql-editor-message") and contains(string(), "ROLLBACK")]' ) @@ -503,36 +326,46 @@ SELECT relname FROM pg_class WHERE relkind IN ('r','s','t') and relnamespace = 2 assert len(el) == 0, "Table '{}' created with auto commit disabled and without any explicit commit.".format(table_name) def _query_tool_auto_commit_enabled(self): + + query = """-- 1. Enable auto commit. +-- 2. END any open transaction. +-- 3. Create table in public schema. +-- 4. ROLLBACK transaction +-- 5. Check if table is created event after ROLLBACK. +END;""" + + self.page.fill_codemirror_area_with(query) + + wait = WebDriverWait(self.page.driver, 10) + + btn_query_dropdown = wait.until(EC.presence_of_element_located( + (By.ID, "btn-query-dropdown"))) + + btn_query_dropdown.click() + + 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() + table_name = 'query_tool_auto_commit_enabled_table' - query = """-- 1. END any open transaction. + query = """-- 1. (Done) END any open transaction. -- 2. Enable auto commit. -- 3. Create table in public schema. -- 4. ROLLBACK transaction -- 5. Check if table is created event after ROLLBACK. -END; CREATE TABLE public.{}();""".format(table_name) - wait = WebDriverWait(self.page.driver, 10) self.page.fill_codemirror_area_with(query) - self.page.find_by_id("btn-query-dropdown").click() - - auto_commit_btn = self.page.find_by_id("btn-auto-commit") - - auto_commit_check = auto_commit_btn.find_element_by_tag_name("i") - - # if auto commit is enabled then 'i' element will - # have 'auto-commit fa fa-check' classes - # if auto commit is disabled then 'i' element will - # have 'auto-commit fa fa-check visibility-hidden' classes - - if 'auto-commit fa fa-check visibility-hidden' == str(auto_commit_check.get_attribute( - 'class')): - auto_commit_btn.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.driver.find_element_by_xpath( + self.page.find_by_xpath( '//div[contains(@class, "sql-editor-message") and contains(string(), "CREATE TABLE")]' ) @@ -547,7 +380,7 @@ ROLLBACK;""" self.page.find_by_id("btn-flash").click() self.page.wait_for_query_tool_loading_indicator_to_disappear() self.page.click_tab('Messages') - self.driver.find_element_by_xpath( + self.page.find_by_xpath( '//div[contains(@class, "sql-editor-message") and contains(string(), "ROLLBACK")]' ) @@ -572,8 +405,8 @@ SELECT relname FROM pg_class WHERE relkind IN ('r','s','t') and relnamespace = 2 def _query_tool_auto_rollback_enabled(self): table_name = 'query_tool_auto_rollback_enabled_table' - query = """-- 1. END any open transaction. --- 2. Enable auto rollback and disable auto commit. + query = """-- 1. Enable auto rollback and disable auto commit. +-- 2. END any open transaction. -- 3. Create table in public schema. -- 4. Generate error in transaction. -- 5. END transaction. @@ -581,6 +414,12 @@ SELECT relname FROM pg_class WHERE relkind IN ('r','s','t') and relnamespace = 2 END;""" self.page.fill_codemirror_area_with(query) + self.page.find_by_id("btn-query-dropdown").click() + + self.page.find_by_id("btn-auto-rollback").click() + + 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() @@ -596,38 +435,10 @@ CREATE TABLE public.{}();""".format(table_name) self.page.fill_codemirror_area_with(query) - self.page.find_by_id("btn-query-dropdown").click() - - auto_rollback_btn = self.page.find_by_id("btn-auto-rollback") - - auto_rollback_check = auto_rollback_btn.find_element_by_tag_name("i") - - # if auto rollback is enabled then 'i' element will - # have 'auto-rollback fa fa-check' classes - # if auto rollback is disabled then 'i' element will - # have 'auto-rollback fa fa-check visibility-hidden' classes - - if 'auto-rollback fa fa-check visibility-hidden' == str(auto_rollback_check.get_attribute( - 'class')): - auto_rollback_btn.click() - - auto_commit_btn = self.page.find_by_id("btn-auto-commit") - - auto_commit_check = auto_commit_btn.find_element_by_tag_name("i") - - # if auto commit is enabled then 'i' element will - # have 'auto-commit fa fa-check' classes - # if auto commit is disabled then 'i' element will - # have 'auto-commit fa fa-check visibility-hidden' classes - - if 'auto-commit fa fa-check' == str(auto_commit_check.get_attribute( - 'class')): - auto_commit_btn.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.driver.find_element_by_xpath( + self.page.find_by_xpath( '//div[contains(@class, "sql-editor-message") and contains(string(), "CREATE TABLE")]' ) diff --git a/web/pgadmin/feature_tests/view_data_dml_queries.py b/web/pgadmin/feature_tests/view_data_dml_queries.py index e8cf598a7..0b2da0c29 100644 --- a/web/pgadmin/feature_tests/view_data_dml_queries.py +++ b/web/pgadmin/feature_tests/view_data_dml_queries.py @@ -199,8 +199,6 @@ CREATE TABLE public.defaults 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') - # wait until all database dependant modules/js are loaded. - time.sleep(5) self.page.toggle_open_tree_item('Schemas') self.page.toggle_open_tree_item('public') self.page.toggle_open_tree_item('Tables') @@ -267,7 +265,7 @@ CREATE TABLE public.defaults cell_xpath = CheckForViewDataTest._get_cell_xpath( 'r'+str(idx), 1 ) - time.sleep(0.4) + time.sleep(0.2) self._update_cell(cell_xpath, config_data[str(idx)]) self.page.find_by_id("btn-save").click() # Save data @@ -300,4 +298,4 @@ CREATE TABLE public.defaults if idx != 1 and not is_new_row: self.assertEquals(cells[idx], config_data[str(idx)][1]) elif is_new_row: - self.assertEquals(cells[idx], config_data[str(idx)][1]) \ No newline at end of file + self.assertEquals(cells[idx], config_data[str(idx)][1]) 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 30b10511b..ef2ab5dae 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 @@ -7,13 +7,9 @@ # ########################################################################## -from selenium.webdriver import ActionChains from regression.python_test_utils import test_utils from regression.feature_utils.base_feature_test import BaseFeatureTest -from selenium.webdriver.support.ui import WebDriverWait -from selenium.webdriver.support import expected_conditions as EC -from selenium.webdriver.common.by import By -import time + class CheckForXssFeatureTest(BaseFeatureTest): """ @@ -53,7 +49,7 @@ class CheckForXssFeatureTest(BaseFeatureTest): def runTest(self): self.page.wait_for_spinner_to_disappear() - self._connects_to_server() + self.page.add_server(self.server) self._tables_node_expandable() self._check_xss_in_browser_tree() self._check_xss_in_properties_tab() @@ -65,7 +61,6 @@ class CheckForXssFeatureTest(BaseFeatureTest): self.page.close_query_tool() def after(self): - time.sleep(1) self.page.remove_server(self.server) connection = test_utils.get_db_connection(self.server['db'], self.server['username'], @@ -75,24 +70,6 @@ class CheckForXssFeatureTest(BaseFeatureTest): self.server['sslmode']) test_utils.drop_database(connection, "acceptance_test_db") - def _connects_to_server(self): - self.page.find_by_xpath("//*[@class='aciTreeText' and .='Servers']").click() - time.sleep(2) - 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("Create")) \ - .perform() - self.page.find_by_partial_link_text("Server...").click() - - server_config = self.server - self.page.fill_input_by_field_name("name", server_config['name']) - self.page.find_by_partial_link_text("Connection").click() - self.page.fill_input_by_field_name("host", server_config['host']) - self.page.fill_input_by_field_name("port", server_config['port']) - self.page.fill_input_by_field_name("username", server_config['username']) - self.page.fill_input_by_field_name("password", server_config['db_password']) - self.page.find_by_xpath("//button[contains(.,'Save')]").click() - def _tables_node_expandable(self): self.page.toggle_open_server(self.server['name']) self.page.toggle_open_tree_item('Databases') @@ -155,10 +132,10 @@ class CheckForXssFeatureTest(BaseFeatureTest): self.page.driver.find_element_by_link_text("Tools").click() self.page.find_by_partial_link_text("Query Tool").click() self.page.click_tab('Query -') - self.page.fill_codemirror_area_with("select ''") - time.sleep(1) + self.page.fill_codemirror_area_with( + "select ''" + ) self.page.find_by_id("btn-flash").click() - wait = WebDriverWait(self.page.driver, 5) result_row = self.page.find_by_xpath( "//*[contains(@class, 'ui-widget-content') and contains(@style, 'top:0px')]" @@ -177,9 +154,4 @@ class CheckForXssFeatureTest(BaseFeatureTest): def _check_escaped_characters(self, source_code, string_to_find, source): # For XSS we need to search against element's html code - if source_code.find(string_to_find) == -1: - # No escaped characters found - assert False, "{0} might be vulnerable to XSS ".format(source) - else: - # escaped characters found - assert True + assert source_code.find(string_to_find) != -1, "{0} might be vulnerable to XSS ".format(source) 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 e847040cc..c927cfedf 100644 --- a/web/pgadmin/feature_tests/xss_checks_pgadmin_debugger_test.py +++ b/web/pgadmin/feature_tests/xss_checks_pgadmin_debugger_test.py @@ -8,9 +8,13 @@ ########################################################################## from selenium.webdriver import ActionChains +from selenium.common.exceptions import TimeoutException from regression.python_test_utils import test_utils from regression.feature_utils.base_feature_test import BaseFeatureTest -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 + class CheckDebuggerForXssFeatureTest(BaseFeatureTest): """Tests to check if Debugger is vulnerable to XSS.""" @@ -30,34 +34,15 @@ class CheckDebuggerForXssFeatureTest(BaseFeatureTest): def runTest(self): self.page.wait_for_spinner_to_disappear() - self._connects_to_server() + self.page.add_server(self.server) self._function_node_expandable() self._debug_function() def after(self): - time.sleep(0.5) test_utils.drop_debug_function(self.server, "postgres", "test_function") self.page.remove_server(self.server) - def _connects_to_server(self): - self.page.find_by_xpath("//*[@class='aciTreeText' and .='Servers']").click() - time.sleep(2) - 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("Create")) \ - .perform() - self.page.find_by_partial_link_text("Server...").click() - - server_config = self.server - self.page.fill_input_by_field_name("name", server_config['name']) - self.page.find_by_partial_link_text("Connection").click() - self.page.fill_input_by_field_name("host", server_config['host']) - self.page.fill_input_by_field_name("port", server_config['port']) - self.page.fill_input_by_field_name("username", server_config['username']) - self.page.fill_input_by_field_name("password", server_config['db_password']) - self.page.find_by_xpath("//button[contains(.,'Save')]").click() - def _function_node_expandable(self): self.page.toggle_open_server(self.server['name']) self.page.toggle_open_tree_item('Databases') @@ -73,32 +58,44 @@ class CheckDebuggerForXssFeatureTest(BaseFeatureTest): .move_to_element(self.page.driver.find_element_by_link_text("Debugging")) \ .perform() self.page.driver.find_element_by_link_text("Debug").click() - time.sleep(0.5) + # We need to check if debugger plugin is installed or not try: - is_error = self.page.find_by_xpath( - "//div[contains(@class,'ajs-header')]" - ).text - except Exception as e: + wait = WebDriverWait(self.page.driver, 2) + is_error = wait.until(EC.presence_of_element_located( + (By.XPATH, "//div[contains(@class,'ajs-header')]")) + ) + except TimeoutException as e: is_error = None # If debugger plugin is not found - if is_error and is_error == "Debugger Error": + if is_error and is_error.text == "Debugger Error": self.page.click_modal('OK') - self.skipTest("Please make sure that debugger plugin is properly configured") + self.skipTest( + "Please make sure that debugger plugin is properly configured" + ) else: - time.sleep(2) - self.page.driver.switch_to.frame(self.page.driver.find_element_by_tag_name('iframe')) - self.page.click_element(self.page.driver.find_elements_by_xpath("//button")[2]) - time.sleep(2) + self.page.driver.switch_to.frame( + self.page.driver.find_element_by_tag_name('iframe') + ) - # Only this tab is vulnerable rest are BackGrid & Code Mirror control - # which are already tested in Query tool test case + wait.until(EC.presence_of_element_located( + (By.XPATH, "//span[contains(.,'Hello, pgAdmin4')]")) + ) + self.page.click_element( + self.page.driver.find_elements_by_xpath("//button")[2] + ) + + wait.until(EC.presence_of_element_located( + (By.XPATH, "//td[contains(@class,'test_function') and contains(.,'Hello, pgAdmin4')]")) + ) + + # Only this tab is vulnerable rest are BackGrid & Code Mirror + # control which are already tested in Query tool test case self.page.click_tab("Messages") source_code = self.page.find_by_xpath( "//*[@id='messages']" ).get_attribute('innerHTML') - self._check_escaped_characters( source_code, 'NOTICE: <img src="x" onerror="console.log(1)">', @@ -107,18 +104,11 @@ class CheckDebuggerForXssFeatureTest(BaseFeatureTest): self._close_debugger() def _close_debugger(self): - time.sleep(0.5) self.page.driver.switch_to_default_content() - time.sleep(0.5) self.page.click_element( self.page.find_by_xpath("//*[@id='dockerContainer']/div/div[3]/div/div[2]/div[1]") ) def _check_escaped_characters(self, source_code, string_to_find, source): # For XSS we need to search against element's html code - if source_code.find(string_to_find) == -1: - # No escaped characters found - assert False, "{0} might be vulnerable to XSS ".format(source) - else: - # escaped characters found - assert True + assert source_code.find(string_to_find) != -1, "{0} might be vulnerable to XSS ".format(source) 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 1adcac067..ea84b5a17 100644 --- a/web/pgadmin/feature_tests/xss_checks_roles_control_test.py +++ b/web/pgadmin/feature_tests/xss_checks_roles_control_test.py @@ -11,6 +11,7 @@ from selenium.webdriver import ActionChains from regression.python_test_utils import test_utils from regression.feature_utils.base_feature_test import BaseFeatureTest + class CheckRoleMembershipControlFeatureTest(BaseFeatureTest): """Tests to check role membership control for xss.""" @@ -22,9 +23,9 @@ class CheckRoleMembershipControlFeatureTest(BaseFeatureTest): def before(self): # Some test function is needed for debugger test_utils.create_role(self.server, "postgres", - "test_role") + "test_role") test_utils.create_role(self.server, "postgres", - "