diff --git a/.pylintrc b/.pylintrc index 543224a..45047df 100644 --- a/.pylintrc +++ b/.pylintrc @@ -137,7 +137,8 @@ disable=print-statement, bad-whitespace, bad-continuation, invalid-name, - wrong-import-position + wrong-import-position, + global-statement # Enable the message, report, category or checker with the given id(s). You can # either give multiple identifier separated by comma (,) or put this option diff --git a/conftest.py b/conftest.py index 0d3e2e1..53d55d7 100644 --- a/conftest.py +++ b/conftest.py @@ -23,17 +23,29 @@ def pytest_addoption( parser ): # NOTE: This file needs to be in the project root for this to work :-/ - # add an option to control which webdriver to use + # add test options parser.addoption( "--webdriver", action="store", dest="webdriver", default="firefox", help="Webdriver to use." ) + parser.addoption( + "--headless", action="store_true", dest="headless", default=False, + help="Run the tests headless." + ) + parser.addoption( + "--window-size", action="store", dest="window_size", default="1000x700", + help="Browser window size." + ) - # add an option to control checking of vehicle/ordnance reports + # add test options + parser.addoption( + "--no-clipboard", action="store_true", dest="no_clipboard", default=False, + help="Don't use the clipboard to get snippets." + ) parser.addoption( "--vo-reports", action="store_true", dest="check_vo_reports", default=False, help="Check the vehicle/ordnance reports." -) + ) # --------------------------------------------------------------------- @@ -46,6 +58,13 @@ def webapp(): def make_webapp_url( endpoint, **kwargs ): """Generate a webapp URL.""" with app.test_request_context(): + if pytest.config.option.headless: #pylint: disable=no-member + # headless browsers have no clipboard support :-/ + pytest.config.option.no_clipboard = True #pylint: disable=no-member + if pytest.config.option.no_clipboard: #pylint: disable=no-member + # NOTE: It's not a bad idea to bypass the clipboard, even when running in a browser, + # to avoid problems if something else uses the clipboard while the tests are running. + kwargs["store_clipboard"] = 1 url = url_for( endpoint, _external=True, **kwargs ) return url.replace( "localhost/", "localhost:{}/".format(FLASK_WEBAPP_PORT) ) app.url_for = make_webapp_url @@ -105,14 +124,23 @@ def webdriver( request ): driver = request.config.getoption( "--webdriver" ) from selenium import webdriver as wb if driver == "firefox": + options = wb.FirefoxOptions() + options.set_headless( headless = pytest.config.option.headless ) #pylint: disable=no-member driver = wb.Firefox( + firefox_options = options, log_path = os.path.join( tempfile.gettempdir(), "geckodriver.log" ) ) elif driver == "chrome": - driver = wb.Chrome() + options = wb.ChromeOptions() + options.set_headless( headless = pytest.config.option.headless ) #pylint: disable=no-member + driver = wb.Chrome( chrome_options=options ) else: assert False, "Unknown webdriver: {}".format( driver ) + # set the browser size + words = pytest.config.option.window_size.split( "x" ) #pylint: disable=no-member + driver.set_window_size( int(words[0]), int(words[1]) ) + # return the webdriver to the caller utils._webdriver = driver #pylint: disable=protected-access yield driver diff --git a/vasl_templates/webapp/static/main.js b/vasl_templates/webapp/static/main.js index d2cdad6..6c15ce5 100644 --- a/vasl_templates/webapp/static/main.js +++ b/vasl_templates/webapp/static/main.js @@ -297,7 +297,7 @@ $(document).ready( function () { template_id = "vehicles" ; else if ( template_id.substring(0,9) === "ordnance_" ) template_id = "ordnance" ; - $( "" ).appendTo( "body" ) ; diff --git a/vasl_templates/webapp/static/snippets.js b/vasl_templates/webapp/static/snippets.js index 426fa26..3537944 100644 --- a/vasl_templates/webapp/static/snippets.js +++ b/vasl_templates/webapp/static/snippets.js @@ -446,7 +446,7 @@ function on_load_scenario() // FOR TESTING PORPOISES! We can't control a file upload from Selenium (since // the browser will use native controls), so we store the result in a
). if ( getUrlParam( "scenario_persistence" ) ) { - var $elem = $( "#scenario_persistence" ) ; // nb: must have already been created + var $elem = $( "#_scenario_persistence_" ) ; // nb: must have already been created do_load_scenario( JSON.parse( $elem.val() ) ) ; return ; } @@ -610,11 +610,11 @@ function on_save_scenario() // FOR TESTING PORPOISES! We can't control a file download from Selenium (since // the browser will use native controls), so we store the result in a
). if ( getUrlParam( "scenario_persistence" ) ) { - var $elem = $( "#scenario_persistence" ) ; + var $elem = $( "#_scenario_persistence_" ) ; if ( $elem.length === 0 ) { // NOTE: The
we store the message in must be visible, otherwise // Selenium doesn't return any text for it :-/ - $elem = $( "" ) ; + $elem = $( "" ) ; $("body").append( $elem ) ; } $elem.val( data ) ; @@ -684,7 +684,7 @@ function on_template_pack() // FOR TESTING PORPOISES! We can't control a file upload from Selenium (since // the browser will use native controls), so we store the result in a
). if ( getUrlParam( "template_pack_persistence" ) ) { - var data = $( "#template_pack_persistence" ).val() ; // nb: must have already been created + var data = $( "#_template_pack_persistence_" ).val() ; // nb: must have already been created var pos = data.indexOf( "|" ) ; var fname = data.substring( 0, pos ).trim() ; data = data.substring( pos+1 ).trim() ; diff --git a/vasl_templates/webapp/static/utils.js b/vasl_templates/webapp/static/utils.js index cb7e62b..df4c355 100644 --- a/vasl_templates/webapp/static/utils.js +++ b/vasl_templates/webapp/static/utils.js @@ -3,6 +3,19 @@ function copyToClipboard( val ) { + if ( getUrlParam( "store_clipboard" ) ) { + // store the value where the tests can retrieve it + var $elem = $("#_clipboard_") ; + if ( $elem.length === 0 ) { + // NOTE: The
we store the message in must be visible, otherwise + // Selenium doesn't return any text for it :-/ + $elem = $( "" ) ; + $("body").append( $elem ) ; + } + $("#_clipboard_").text( val ) ; + return ; + } + // IE-specific code path to prevent textarea being shown while dialog is visible if ( window.clipboardData && window.clipboardData.setData ) { clipboardData.setData( "Text", val ) ; diff --git a/vasl_templates/webapp/templates/index.html b/vasl_templates/webapp/templates/index.html index 1612365..0005efd 100644 --- a/vasl_templates/webapp/templates/index.html +++ b/vasl_templates/webapp/templates/index.html @@ -22,9 +22,10 @@ -
+ +
diff --git a/vasl_templates/webapp/tests/test_scenario_persistence.py b/vasl_templates/webapp/tests/test_scenario_persistence.py index 35438c1..c9145d7 100644 --- a/vasl_templates/webapp/tests/test_scenario_persistence.py +++ b/vasl_templates/webapp/tests/test_scenario_persistence.py @@ -182,11 +182,11 @@ def test_unknown_vo( webapp, webdriver ): def _load_scenario( scenario ): """Load a scenario into the UI.""" - set_stored_msg( "scenario_persistence", json.dumps(scenario) ) + set_stored_msg( "_scenario_persistence_", json.dumps(scenario) ) select_menu_option( "load_scenario" ) def _save_scenario(): """Save the scenario.""" select_menu_option( "save_scenario" ) - data = get_stored_msg( "scenario_persistence" ) + data = get_stored_msg( "_scenario_persistence_" ) return json.loads( data ) diff --git a/vasl_templates/webapp/tests/test_snippets.py b/vasl_templates/webapp/tests/test_snippets.py index f26a765..b599a31 100644 --- a/vasl_templates/webapp/tests/test_snippets.py +++ b/vasl_templates/webapp/tests/test_snippets.py @@ -179,7 +179,7 @@ def test_edit_templates( webapp, webdriver ): if template_id in("scenario_note","ob_setup","ob_note"): return # nb: these require special handling (done below) # edit the template - elem = find_child( "a.edit-template-link[data-id='{}']".format( template_id ) ) + elem = find_child( "a._edit-template-link_[data-id='{}']".format( template_id ) ) webdriver.execute_script( "$(arguments[0]).click();", elem ) edit_template( orig_template_id ) # check that the new template is being used diff --git a/vasl_templates/webapp/tests/test_template_packs.py b/vasl_templates/webapp/tests/test_template_packs.py index 64482e2..8b65631 100644 --- a/vasl_templates/webapp/tests/test_template_packs.py +++ b/vasl_templates/webapp/tests/test_template_packs.py @@ -30,7 +30,7 @@ def test_individual_files( webapp, webdriver ): assert clipboard != "" # upload a new template fname = template_id + ".j2" - set_stored_msg( "template_pack_persistence", + set_stored_msg( "_template_pack_persistence_", "{} | {}".format( fname, "UPLOADED TEMPLATE" ) ) select_menu_option( "template_pack" ) @@ -41,7 +41,7 @@ def test_individual_files( webapp, webdriver ): for_each_template( test_template ) # try uploading a template with an incorrect filename extension - set_stored_msg( "template_pack_persistence", + set_stored_msg( "_template_pack_persistence_", "filename.xyz | UPLOADED TEMPLATE" ) select_menu_option( "template_pack" ) @@ -49,7 +49,7 @@ def test_individual_files( webapp, webdriver ): assert "Invalid template extension" in last_error_msg # try uploading a template with an unknown filename - set_stored_msg( "template_pack_persistence", + set_stored_msg( "_template_pack_persistence_", "unknown.j2 | UPLOADED TEMPLATE" ) select_menu_option( "template_pack" ) @@ -203,7 +203,7 @@ def _generate_snippet( template_id, orig_template_id ): def _upload_template_pack( zip_data ): """Upload a template pack.""" - set_stored_msg( "template_pack_persistence", + set_stored_msg( "_template_pack_persistence_", "{} | {}".format( "test.zip", base64.b64encode(zip_data).decode("ascii") ) ) select_menu_option( "template_pack" ) diff --git a/vasl_templates/webapp/tests/utils.py b/vasl_templates/webapp/tests/utils.py index 8d1dc3c..2827129 100644 --- a/vasl_templates/webapp/tests/utils.py +++ b/vasl_templates/webapp/tests/utils.py @@ -6,6 +6,7 @@ import json import time import re +import pytest from PyQt5.QtWidgets import QApplication from selenium.webdriver.support.ui import Select from selenium.webdriver.common.keys import Keys @@ -316,11 +317,18 @@ def click_dialog_button( caption ): # --------------------------------------------------------------------- +_pyqt_app = None + def get_clipboard() : """Get the contents of the clipboard.""" - app = QApplication( [] ) #pylint: disable=unused-variable - clipboard = QApplication.clipboard() - return clipboard.text() + if pytest.config.option.no_clipboard: #pylint: disable=no-member + return get_stored_msg( "_clipboard_" ) + else: + global _pyqt_app + if _pyqt_app is None: + _pyqt_app = QApplication( [] ) + clipboard = QApplication.clipboard() + return clipboard.text() def wait_for( timeout, func ): """Wait for a condition to become true."""