Cleanup feature tests. Fixes #2586

pull/6/head
Harshal Dhumal 2017-08-29 14:57:56 +01:00 committed by Dave Page
parent 401e13ca65
commit ceb9438000
10 changed files with 183 additions and 533 deletions

View File

@ -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')

View File

@ -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()

View File

@ -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

View File

@ -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):

View File

@ -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")]'
)

View File

@ -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])
self.assertEquals(cells[idx], config_data[str(idx)][1])

View File

@ -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 '<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 +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)

View File

@ -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: &lt;img src="x" onerror="console.log(1)"&gt;',
@ -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)

View File

@ -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",
"<h1>test</h1>")
"<h1>test</h1>")
def runTest(self):
self.page.wait_for_spinner_to_disappear()
@ -34,9 +35,9 @@ class CheckRoleMembershipControlFeatureTest(BaseFeatureTest):
def after(self):
test_utils.drop_role(self.server, "postgres",
"test_role")
"test_role")
test_utils.drop_role(self.server, "postgres",
"<h1>test</h1>")
"<h1>test</h1>")
self.page.remove_server(self.server)
def _connects_to_server(self):
@ -77,12 +78,6 @@ class CheckRoleMembershipControlFeatureTest(BaseFeatureTest):
)
self.page.find_by_xpath("//button[contains(.,'Cancel')]").click()
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)

View File

@ -8,10 +8,9 @@
##########################################################################
import time
import math
from selenium.common.exceptions import NoSuchElementException, \
WebDriverException, StaleElementReferenceException
WebDriverException
from selenium.webdriver import ActionChains
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.support import expected_conditions as EC
@ -180,9 +179,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 +199,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') "