mirror of
https://github.com/pgadmin-org/pgadmin4.git
synced 2025-02-25 18:55:31 -06:00
Support running feature tests against Firefox. Fixes #3270
This commit is contained in:
parent
8d9e9eab13
commit
ccf58570b1
1
.gitignore
vendored
1
.gitignore
vendored
@ -36,6 +36,7 @@ runtime/pgAdmin4_resource.rc
|
|||||||
runtime/release/
|
runtime/release/
|
||||||
runtime/ui_BrowserWindow.h
|
runtime/ui_BrowserWindow.h
|
||||||
web/config_local.py
|
web/config_local.py
|
||||||
|
web/geckodriver.log
|
||||||
web/regression/test_config.json
|
web/regression/test_config.json
|
||||||
node_modules/
|
node_modules/
|
||||||
web/pgAdmin/static/js/generated
|
web/pgAdmin/static/js/generated
|
||||||
|
@ -200,7 +200,7 @@ class CopySelectedQueryResultsFeatureTest(BaseFeatureTest):
|
|||||||
ActionChains(self.page.driver).key_down(
|
ActionChains(self.page.driver).key_down(
|
||||||
Keys.CONTROL).send_keys('c').key_up(Keys.CONTROL).perform()
|
Keys.CONTROL).send_keys('c').key_up(Keys.CONTROL).perform()
|
||||||
|
|
||||||
self.assertEqual('"cool info"', pyperclip.paste())
|
self.assertIn('"cool info"', pyperclip.paste())
|
||||||
|
|
||||||
def after(self):
|
def after(self):
|
||||||
self.page.close_query_tool()
|
self.page.close_query_tool()
|
||||||
|
@ -185,6 +185,8 @@ CREATE TABLE public.defaults_{0}
|
|||||||
(By.XPATH, xpath)), CheckForViewDataTest.TIMEOUT_STRING
|
(By.XPATH, xpath)), CheckForViewDataTest.TIMEOUT_STRING
|
||||||
)
|
)
|
||||||
cell_el = self.page.find_by_xpath(xpath)
|
cell_el = self.page.find_by_xpath(xpath)
|
||||||
|
self.page.driver.execute_script("arguments[0].scrollIntoView()",
|
||||||
|
cell_el)
|
||||||
ActionChains(self.driver).move_to_element(cell_el).double_click(
|
ActionChains(self.driver).move_to_element(cell_el).double_click(
|
||||||
cell_el
|
cell_el
|
||||||
).perform()
|
).perform()
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
##########################################################################
|
##########################################################################
|
||||||
|
|
||||||
import os
|
import os
|
||||||
|
import time
|
||||||
from selenium.webdriver.common.keys import Keys
|
from selenium.webdriver.common.keys import Keys
|
||||||
from selenium.webdriver.support.ui import WebDriverWait
|
from selenium.webdriver.support.ui import WebDriverWait
|
||||||
from selenium.webdriver.common.by import By
|
from selenium.webdriver.common.by import By
|
||||||
@ -98,7 +99,18 @@ class CheckFileManagerFeatureTest(BaseFeatureTest):
|
|||||||
self.page.find_by_id("file-input-path").send_keys(
|
self.page.find_by_id("file-input-path").send_keys(
|
||||||
Keys.RETURN
|
Keys.RETURN
|
||||||
)
|
)
|
||||||
contents = self.page.find_by_id("contents").get_attribute('innerHTML')
|
|
||||||
|
if self.page.driver.capabilities['browserName'] == 'firefox':
|
||||||
|
table = self.page.wait_for_element_to_reload(
|
||||||
|
lambda driver:
|
||||||
|
driver.find_element_by_css_selector("table#contents")
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
table = self.page.driver \
|
||||||
|
.find_element_by_css_selector("table#contents")
|
||||||
|
|
||||||
|
contents = table.get_attribute('innerHTML')
|
||||||
|
|
||||||
self.page.click_modal('Cancel')
|
self.page.click_modal('Cancel')
|
||||||
self.page.wait_for_query_tool_loading_indicator_to_disappear()
|
self.page.wait_for_query_tool_loading_indicator_to_disappear()
|
||||||
self._check_escaped_characters(
|
self._check_escaped_characters(
|
||||||
|
@ -127,6 +127,15 @@ Python Tests:
|
|||||||
https://sites.google.com/a/chromium.org/chromedriver/downloads or a
|
https://sites.google.com/a/chromium.org/chromedriver/downloads or a
|
||||||
package manager and make sure it is in the PATH
|
package manager and make sure it is in the PATH
|
||||||
|
|
||||||
|
- For feature tests to run on Firefox, geckodriver need to be installed;
|
||||||
|
- Get geckodriver from https://github.com/mozilla/geckodriver/releases.
|
||||||
|
- Extract the binary and run chmod +x geckodriver.
|
||||||
|
- Copy geckodriver into /usr/local/bin or make sure path of the
|
||||||
|
geckodriver must be specified in the PATH.
|
||||||
|
- Set the "default_browser" parameter in test_config file or pass the command
|
||||||
|
line option --default_browser. Supported browsers are "Chrome" and
|
||||||
|
"Firefox".
|
||||||
|
|
||||||
- The test framework is modular and pluggable and dynamically locates tests
|
- The test framework is modular and pluggable and dynamically locates tests
|
||||||
for modules which are discovered at runtime. All test cases are found
|
for modules which are discovered at runtime. All test cases are found
|
||||||
and registered automatically by its module name in
|
and registered automatically by its module name in
|
||||||
|
@ -12,6 +12,7 @@ import signal
|
|||||||
import random
|
import random
|
||||||
|
|
||||||
import time
|
import time
|
||||||
|
from selenium.common.exceptions import WebDriverException
|
||||||
|
|
||||||
|
|
||||||
class AppStarter:
|
class AppStarter:
|
||||||
@ -41,11 +42,27 @@ class AppStarter:
|
|||||||
env=env
|
env=env
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def launch_browser(retry_count):
|
||||||
|
try:
|
||||||
self.driver.get(
|
self.driver.get(
|
||||||
"http://" + self.app_config.DEFAULT_SERVER + ":" +
|
"http://" + self.app_config.DEFAULT_SERVER + ":" +
|
||||||
random_server_port
|
random_server_port
|
||||||
)
|
)
|
||||||
|
|
||||||
|
except WebDriverException as e:
|
||||||
|
# In case of WebDriverException sleep for 1 second and retry
|
||||||
|
# again. Retry 10 times and if still app will not start then
|
||||||
|
# raise exception.
|
||||||
|
time.sleep(1)
|
||||||
|
if retry_count < 60:
|
||||||
|
retry_count = retry_count + 1
|
||||||
|
launch_browser(retry_count)
|
||||||
|
else:
|
||||||
|
raise Exception('Unable to start python server even after '
|
||||||
|
'retrying 60 times.')
|
||||||
|
|
||||||
|
launch_browser(0)
|
||||||
|
|
||||||
def stop_app(self):
|
def stop_app(self):
|
||||||
""" This function stop the started app by killing process """
|
""" This function stop the started app by killing process """
|
||||||
self.driver.quit()
|
self.driver.quit()
|
||||||
|
@ -60,6 +60,8 @@ class PgadminPage:
|
|||||||
self.fill_input_by_field_name("port", server_config['port'])
|
self.fill_input_by_field_name("port", server_config['port'])
|
||||||
self.fill_input_by_field_name("username", server_config['username'])
|
self.fill_input_by_field_name("username", server_config['username'])
|
||||||
self.fill_input_by_field_name("password", server_config['db_password'])
|
self.fill_input_by_field_name("password", server_config['db_password'])
|
||||||
|
# Required sleep to avoid "fe_sendauth" password error.
|
||||||
|
time.sleep(0.5)
|
||||||
self.find_by_xpath("//button[contains(.,'Save')]").click()
|
self.find_by_xpath("//button[contains(.,'Save')]").click()
|
||||||
|
|
||||||
self.find_by_xpath(
|
self.find_by_xpath(
|
||||||
@ -318,6 +320,14 @@ class PgadminPage:
|
|||||||
|
|
||||||
self._wait_for("app to start", page_shows_app, self.app_start_timeout)
|
self._wait_for("app to start", page_shows_app, self.app_start_timeout)
|
||||||
|
|
||||||
|
def wait_for_element_to_reload(self, element_selector):
|
||||||
|
WebDriverWait(self.driver, 20) \
|
||||||
|
.until(EC.staleness_of(element_selector(self.driver)))
|
||||||
|
WebDriverWait(self.driver, 20) \
|
||||||
|
.until_not(EC.staleness_of(element_selector(self.driver)))
|
||||||
|
|
||||||
|
return element_selector(self.driver)
|
||||||
|
|
||||||
def _wait_for(self, waiting_for_message, condition_met_function,
|
def _wait_for(self, waiting_for_message, condition_met_function,
|
||||||
timeout=None):
|
timeout=None):
|
||||||
if timeout is None:
|
if timeout is None:
|
||||||
|
@ -22,6 +22,7 @@ import json
|
|||||||
|
|
||||||
from selenium import webdriver
|
from selenium import webdriver
|
||||||
from selenium.webdriver.chrome.options import Options
|
from selenium.webdriver.chrome.options import Options
|
||||||
|
from selenium.webdriver.common.desired_capabilities import DesiredCapabilities
|
||||||
|
|
||||||
if sys.version_info < (2, 7):
|
if sys.version_info < (2, 7):
|
||||||
import unittest2 as unit_test
|
import unittest2 as unit_test
|
||||||
@ -181,6 +182,32 @@ def get_test_modules(arguments):
|
|||||||
exclude_pkgs += arguments['exclude'].split(',')
|
exclude_pkgs += arguments['exclude'].split(',')
|
||||||
|
|
||||||
if 'feature_tests' not in exclude_pkgs:
|
if 'feature_tests' not in exclude_pkgs:
|
||||||
|
default_browser = 'chrome'
|
||||||
|
|
||||||
|
# Check default browser provided through command line. If provided
|
||||||
|
# then use that browser as default browser else check for the setting
|
||||||
|
# provided in test_config.json file.
|
||||||
|
if (
|
||||||
|
'default_browser' in arguments and
|
||||||
|
arguments['default_browser'] is not None
|
||||||
|
):
|
||||||
|
default_browser = arguments['default_browser'].lower()
|
||||||
|
elif (
|
||||||
|
test_setup.config_data and
|
||||||
|
"default_browser" in test_setup.config_data
|
||||||
|
):
|
||||||
|
default_browser = test_setup.config_data['default_browser'].lower()
|
||||||
|
|
||||||
|
if default_browser == 'firefox':
|
||||||
|
cap = DesiredCapabilities.FIREFOX
|
||||||
|
cap['requireWindowFocus'] = True
|
||||||
|
cap['enablePersistentHover'] = False
|
||||||
|
profile = webdriver.FirefoxProfile()
|
||||||
|
profile.set_preference("dom.disable_beforeunload", True)
|
||||||
|
driver = webdriver.Firefox(capabilities=cap,
|
||||||
|
firefox_profile=profile)
|
||||||
|
driver.implicitly_wait(1)
|
||||||
|
else:
|
||||||
options = Options()
|
options = Options()
|
||||||
if test_setup.config_data:
|
if test_setup.config_data:
|
||||||
if 'headless_chrome' in test_setup.config_data:
|
if 'headless_chrome' in test_setup.config_data:
|
||||||
@ -188,6 +215,7 @@ def get_test_modules(arguments):
|
|||||||
options.add_argument("--headless")
|
options.add_argument("--headless")
|
||||||
options.add_argument("--window-size=1280x1024")
|
options.add_argument("--window-size=1280x1024")
|
||||||
driver = webdriver.Chrome(chrome_options=options)
|
driver = webdriver.Chrome(chrome_options=options)
|
||||||
|
|
||||||
app_starter = AppStarter(driver, config)
|
app_starter = AppStarter(driver, config)
|
||||||
app_starter.start_app()
|
app_starter.start_app()
|
||||||
|
|
||||||
@ -229,6 +257,10 @@ def add_arguments():
|
|||||||
help='Skips execution of the test cases of particular package and '
|
help='Skips execution of the test cases of particular package and '
|
||||||
'sub-packages'
|
'sub-packages'
|
||||||
)
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
'--default_browser',
|
||||||
|
help='Executes the feature test in specific browser'
|
||||||
|
)
|
||||||
arg = parser.parse_args()
|
arg = parser.parse_args()
|
||||||
|
|
||||||
return arg
|
return arg
|
||||||
@ -341,7 +373,12 @@ if __name__ == '__main__':
|
|||||||
sys.stderr = StreamToLogger(stderr_logger, logging.ERROR)
|
sys.stderr = StreamToLogger(stderr_logger, logging.ERROR)
|
||||||
args = vars(add_arguments())
|
args = vars(add_arguments())
|
||||||
# Get test module list
|
# Get test module list
|
||||||
|
try:
|
||||||
test_module_list = get_test_modules(args)
|
test_module_list = get_test_modules(args)
|
||||||
|
except Exception as e:
|
||||||
|
print(str(e))
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
# Login the test client
|
# Login the test client
|
||||||
test_utils.login_tester_account(test_client)
|
test_utils.login_tester_account(test_client)
|
||||||
|
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
{
|
{
|
||||||
"headless_chrome": false,
|
"headless_chrome": false,
|
||||||
|
"default_browser": "Chrome",
|
||||||
"pgAdmin4_login_credentials": {
|
"pgAdmin4_login_credentials": {
|
||||||
"new_password": "NEWPASSWORD",
|
"new_password": "NEWPASSWORD",
|
||||||
"login_password": "PASSWORD",
|
"login_password": "PASSWORD",
|
||||||
|
Loading…
Reference in New Issue
Block a user