Hi,

Please find attached patch to improve feature test execution time.
Now on my machine overall execution time is cut down to 280 seconds from
400+ seconds

Changes:

1. Removed fixed python time.sleeps where ever possible.
2. Removed connect to server test cases.
3. Query tool test cases:
     i. Merged 3 test cases On demand result on scroll, grid select all and
column select all.
     ii. Merged 3 test cases Explain query, Explain query with verbose and
Explain query with cost.
     iii. Merged 3 test cases Explain analyze query, Explain analyze with
buffers and Explain analyze             with timing.
4. Improved debugger XSS test case execution time.

-- 
*Harshal Dhumal*
*Sr. Software Engineer*

EnterpriseDB India: http://www.enterprisedb.com
The Enterprise PostgreSQL Company
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 97e96f2..0000000
--- 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 1809d45..d01bf66 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 f700aab..46a1beb 100644
--- a/web/pgadmin/feature_tests/pg_datatype_validation_test.py
+++ b/web/pgadmin/feature_tests/pg_datatype_validation_test.py
@@ -6,7 +6,6 @@
 # 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
@@ -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')
diff --git a/web/pgadmin/feature_tests/query_tool_journey_test.py b/web/pgadmin/feature_tests/query_tool_journey_test.py
index 0795028..dbe287b 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,11 @@ class QueryToolJourneyTest(BaseFeatureTest):
 
     def runTest(self):
         self._navigate_to_query_tool()
-        self._execute_query("SELECT * FROM test_table ORDER BY value")
+
+        self.page.fill_codemirror_area_with(
+            "SELECT * FROM test_table ORDER BY value"
+        )
+        self.page.find_by_id("btn-flash").click()
 
         self._test_copies_rows()
         self._test_copies_columns()
@@ -47,7 +50,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()
@@ -72,7 +74,8 @@ class QueryToolJourneyTest(BaseFeatureTest):
         self.__clear_query_tool()
         editor_input = self.page.find_by_id("output-panel")
         self.page.click_element(editor_input)
-        self._execute_query("SELECT * FROM shoes")
+        self.page.fill_codemirror_area_with("SELECT * FROM shoes")
+        self.page.find_by_id("btn-flash").click()
 
         self.page.click_tab("History")
         selected_history_entry = self.page.find_by_css_selector("#query_list .selected")
@@ -94,7 +97,8 @@ class QueryToolJourneyTest(BaseFeatureTest):
         self.__clear_query_tool()
         self.page.click_element(editor_input)
         for _ in range(15):
-            self._execute_query("SELECT * FROM hats")
+            self.page.fill_codemirror_area_with("SELECT * FROM hats")
+            self.page.find_by_id("btn-flash").click()
 
         self.page.click_tab("History")
         query_we_need_to_scroll_to = self.page.find_by_xpath(
@@ -126,13 +130,6 @@ 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.find_by_id("btn-flash").click()
 
     def _assert_clickable(self, element):
         self.page.click_element(element)
diff --git a/web/pgadmin/feature_tests/query_tool_tests.py b/web/pgadmin/feature_tests/query_tool_tests.py
index 8e13817..c747beb 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... ",
-              file=sys.stderr, end="")
-        self._on_demand_result_select_all_grid()
-        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 query with verbose and cost
+        print("Explain query with verbose and cost... ",
               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()
+        self._query_tool_explain_with_verbose_and_cost()
         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()
+        # explain analyze query with buffers and timing
+        print("Explain analyze query with buffers and timing... ",
+              file=sys.stderr, end="")
+        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')
@@ -180,14 +114,24 @@ class QueryToolFeatureTest(BaseFeatureTest):
         )
         self.page.click_modal('Yes')
 
+    def _wait_until_canvas_updates(self, canvas, old_height):
+        # loop until canvas height changes or upto 5 seconds.
+        cur_time = time.time()
+        while canvas.size['height'] == old_height \
+                and cur_time + 5 > time.time():
+            pass
+
     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()
@@ -197,154 +141,83 @@ SELECT generate_series(1, {}) as id""".format(
         canvas = wait.until(EC.presence_of_element_located(
             (By.CSS_SELECTOR, "#datagrid .slick-viewport .grid-canvas")))
 
+        old_height = canvas.size['height']
         # 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());"
-        )
-
-        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)
+        self._wait_until_canvas_updates(canvas, old_height)
 
-        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()
 
-        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"))
-        )
-
-        row_id_to_find = config.ON_DEMAND_RECORD_COUNT * ON_DEMAND_CHUNKS
+            (By.CSS_SELECTOR, "#datagrid .slick-viewport .grid-canvas")))
 
-        canvas.find_element_by_xpath(
-            '//span[text()="{}"]'.format(row_id_to_find)
-        )
+        old_height = canvas.size['height']
 
-    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.until(EC.presence_of_element_located(
+            (By.CSS_SELECTOR, ".slick-header-column"))).click()
 
-        wait = WebDriverWait(self.page.driver, 10)
+        self._wait_until_canvas_updates(canvas, old_height)
 
-        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()
 
-        # click on first data column to select all column.
+        canvas = wait.until(EC.presence_of_element_located(
+            (By.CSS_SELECTOR, "#datagrid .slick-viewport .grid-canvas")))
+
+        old_height = canvas.size['height']
 
+        # 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.
+        self._wait_until_canvas_updates(canvas, old_height)
+
+        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-verbose").click()
 
         self.page.find_by_id("btn-explain-costs").click()
 
@@ -357,32 +230,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
-        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')
+        # Search for 'Output' word in result (verbose option)
+        canvas.find_element_by_xpath("//*[contains(string(), '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')]")
+        # Search for 'Total Cost' word in result (cost option)
+        canvas.find_element_by_xpath("//*[contains(string(),'Total Cost')]")
 
-    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 +254,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 +265,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'
diff --git a/web/pgadmin/feature_tests/view_data_dml_queries.py b/web/pgadmin/feature_tests/view_data_dml_queries.py
index e8cf598..0b2da0c 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 30b1051..7e3a9f8 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
@@ -10,10 +10,7 @@
 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 +50,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 +62,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 +71,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 +133,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 '<img src=\"x\" onerror=\"console.log(1)\">'")
-        time.sleep(1)
+        self.page.fill_codemirror_area_with(
+            "select '<img src=\"x\" onerror=\"console.log(1)\">'"
+        )
         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 +155,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 e847040..f18cde2 100644
--- a/web/pgadmin/feature_tests/xss_checks_pgadmin_debugger_test.py
+++ b/web/pgadmin/feature_tests/xss_checks_pgadmin_debugger_test.py
@@ -7,10 +7,15 @@
 #
 ##########################################################################
 
+import time
 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 +35,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 +59,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')
+            )
+
+            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]
+            )
 
-            # 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, "//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:  &lt;img src="x" onerror="console.log(1)"&gt;',
@@ -107,18 +105,12 @@ 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
+        # No escaped characters found
+        assert source_code.find(string_to_find) != -1, "{0} might be vulnerable to XSS ".format(source)
diff --git a/web/regression/feature_utils/pgadmin_page.py b/web/regression/feature_utils/pgadmin_page.py
index 21e45a6..50c1cb1 100644
--- a/web/regression/feature_utils/pgadmin_page.py
+++ b/web/regression/feature_utils/pgadmin_page.py
@@ -180,9 +180,6 @@ class PgadminPage:
         self.wait_for_input_field_content(field_name, field_content)
 
     def fill_codemirror_area_with(self, field_content):
-        # For long text, if we try to execute send_keys and perform back to back, then the actions are
-        # not executed properly as the driver can send only 50 to 60 characters. To avoid this, sleep
-        # on the basis of content length.
         def find_codemirror(driver):
             try:
                 driver.switch_to.default_content()
@@ -203,8 +200,6 @@ class PgadminPage:
         action = ActionChains(self.driver)
         action.send_keys(field_content)
         action.perform()
-        sleep_time = math.ceil(len(field_content) / 50)
-        time.sleep(sleep_time)
 
     def click_tab(self, tab_name):
         tab = self.find_by_xpath("//*[contains(@class,'wcTabTop')]//*[contains(@class,'wcPanelTab') "

Reply via email to