Allow tests to be run headless.

master
Pacman Ghost 6 years ago
parent dbc5292926
commit 971e902988
  1. 3
      .pylintrc
  2. 36
      conftest.py
  3. 2
      vasl_templates/webapp/static/main.js
  4. 8
      vasl_templates/webapp/static/snippets.js
  5. 13
      vasl_templates/webapp/static/utils.js
  6. 3
      vasl_templates/webapp/templates/index.html
  7. 4
      vasl_templates/webapp/tests/test_scenario_persistence.py
  8. 2
      vasl_templates/webapp/tests/test_snippets.py
  9. 8
      vasl_templates/webapp/tests/test_template_packs.py
  10. 14
      vasl_templates/webapp/tests/utils.py

@ -137,7 +137,8 @@ disable=print-statement,
bad-whitespace, bad-whitespace,
bad-continuation, bad-continuation,
invalid-name, invalid-name,
wrong-import-position wrong-import-position,
global-statement
# Enable the message, report, category or checker with the given id(s). You can # 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 # either give multiple identifier separated by comma (,) or put this option

@ -23,17 +23,29 @@ def pytest_addoption( parser ):
# NOTE: This file needs to be in the project root for this to work :-/ # 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( parser.addoption(
"--webdriver", action="store", dest="webdriver", default="firefox", "--webdriver", action="store", dest="webdriver", default="firefox",
help="Webdriver to use." 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( parser.addoption(
"--vo-reports", action="store_true", dest="check_vo_reports", default=False, "--vo-reports", action="store_true", dest="check_vo_reports", default=False,
help="Check the vehicle/ordnance reports." help="Check the vehicle/ordnance reports."
) )
# --------------------------------------------------------------------- # ---------------------------------------------------------------------
@ -46,6 +58,13 @@ def webapp():
def make_webapp_url( endpoint, **kwargs ): def make_webapp_url( endpoint, **kwargs ):
"""Generate a webapp URL.""" """Generate a webapp URL."""
with app.test_request_context(): 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 ) url = url_for( endpoint, _external=True, **kwargs )
return url.replace( "localhost/", "localhost:{}/".format(FLASK_WEBAPP_PORT) ) return url.replace( "localhost/", "localhost:{}/".format(FLASK_WEBAPP_PORT) )
app.url_for = make_webapp_url app.url_for = make_webapp_url
@ -105,14 +124,23 @@ def webdriver( request ):
driver = request.config.getoption( "--webdriver" ) driver = request.config.getoption( "--webdriver" )
from selenium import webdriver as wb from selenium import webdriver as wb
if driver == "firefox": if driver == "firefox":
options = wb.FirefoxOptions()
options.set_headless( headless = pytest.config.option.headless ) #pylint: disable=no-member
driver = wb.Firefox( driver = wb.Firefox(
firefox_options = options,
log_path = os.path.join( tempfile.gettempdir(), "geckodriver.log" ) log_path = os.path.join( tempfile.gettempdir(), "geckodriver.log" )
) )
elif driver == "chrome": 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: else:
assert False, "Unknown webdriver: {}".format( driver ) 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 # return the webdriver to the caller
utils._webdriver = driver #pylint: disable=protected-access utils._webdriver = driver #pylint: disable=protected-access
yield driver yield driver

@ -297,7 +297,7 @@ $(document).ready( function () {
template_id = "vehicles" ; template_id = "vehicles" ;
else if ( template_id.substring(0,9) === "ordnance_" ) else if ( template_id.substring(0,9) === "ordnance_" )
template_id = "ordnance" ; template_id = "ordnance" ;
$( "<a href='#' class='edit-template-link' data-id='" + template_id + "'" + $( "<a href='#' class='_edit-template-link_' data-id='" + template_id + "'" +
" onclick='edit_template(\"" + template_id + "\")'" + " onclick='edit_template(\"" + template_id + "\")'" +
"></a>" "></a>"
).appendTo( "body" ) ; ).appendTo( "body" ) ;

@ -446,7 +446,7 @@ function on_load_scenario()
// FOR TESTING PORPOISES! We can't control a file upload from Selenium (since // 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 <div>). // the browser will use native controls), so we store the result in a <div>).
if ( getUrlParam( "scenario_persistence" ) ) { 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() ) ) ; do_load_scenario( JSON.parse( $elem.val() ) ) ;
return ; return ;
} }
@ -610,11 +610,11 @@ function on_save_scenario()
// FOR TESTING PORPOISES! We can't control a file download from Selenium (since // 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 <div>). // the browser will use native controls), so we store the result in a <div>).
if ( getUrlParam( "scenario_persistence" ) ) { if ( getUrlParam( "scenario_persistence" ) ) {
var $elem = $( "#scenario_persistence" ) ; var $elem = $( "#_scenario_persistence_" ) ;
if ( $elem.length === 0 ) { if ( $elem.length === 0 ) {
// NOTE: The <div> we store the message in must be visible, otherwise // NOTE: The <div> we store the message in must be visible, otherwise
// Selenium doesn't return any text for it :-/ // Selenium doesn't return any text for it :-/
$elem = $( "<textarea id='scenario_persistence' style='z-index-999;'></textarea>" ) ; $elem = $( "<textarea id='_scenario_persistence_' style='z-index-999;'></textarea>" ) ;
$("body").append( $elem ) ; $("body").append( $elem ) ;
} }
$elem.val( data ) ; $elem.val( data ) ;
@ -684,7 +684,7 @@ function on_template_pack()
// FOR TESTING PORPOISES! We can't control a file upload from Selenium (since // 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 <div>). // the browser will use native controls), so we store the result in a <div>).
if ( getUrlParam( "template_pack_persistence" ) ) { 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 pos = data.indexOf( "|" ) ;
var fname = data.substring( 0, pos ).trim() ; var fname = data.substring( 0, pos ).trim() ;
data = data.substring( pos+1 ).trim() ; data = data.substring( pos+1 ).trim() ;

@ -3,6 +3,19 @@
function copyToClipboard( val ) 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 <div> we store the message in must be visible, otherwise
// Selenium doesn't return any text for it :-/
$elem = $( "<textarea id='_clipboard_' style='z-index-999;'></textarea>" ) ;
$("body").append( $elem ) ;
}
$("#_clipboard_").text( val ) ;
return ;
}
// IE-specific code path to prevent textarea being shown while dialog is visible // IE-specific code path to prevent textarea being shown while dialog is visible
if ( window.clipboardData && window.clipboardData.setData ) { if ( window.clipboardData && window.clipboardData.setData ) {
clipboardData.setData( "Text", val ) ; clipboardData.setData( "Text", val ) ;

@ -22,9 +22,10 @@
<input type="button" value="actions"> <input type="button" value="actions">
<input id="load-scenario" type="file" accept=".json" style="display:none;"> <input id="load-scenario" type="file" accept=".json" style="display:none;">
<input id="load-template-pack" type="file" accept=".zip,.j2" style="display:none;"> <input id="load-template-pack" type="file" accept=".zip,.j2" style="display:none;">
<textarea id="template_pack_persistence" style="display:none;"></textarea>
</div> </div>
<textarea id="_template_pack_persistence_" style="display:none;"></textarea>
<!-- ----------------------------------------------------------------- --> <!-- ----------------------------------------------------------------- -->
<div id="tabs"> <div id="tabs">

@ -182,11 +182,11 @@ def test_unknown_vo( webapp, webdriver ):
def _load_scenario( scenario ): def _load_scenario( scenario ):
"""Load a scenario into the UI.""" """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" ) select_menu_option( "load_scenario" )
def _save_scenario(): def _save_scenario():
"""Save the scenario.""" """Save the scenario."""
select_menu_option( "save_scenario" ) select_menu_option( "save_scenario" )
data = get_stored_msg( "scenario_persistence" ) data = get_stored_msg( "_scenario_persistence_" )
return json.loads( data ) return json.loads( data )

@ -179,7 +179,7 @@ def test_edit_templates( webapp, webdriver ):
if template_id in("scenario_note","ob_setup","ob_note"): if template_id in("scenario_note","ob_setup","ob_note"):
return # nb: these require special handling (done below) return # nb: these require special handling (done below)
# edit the template # 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 ) webdriver.execute_script( "$(arguments[0]).click();", elem )
edit_template( orig_template_id ) edit_template( orig_template_id )
# check that the new template is being used # check that the new template is being used

@ -30,7 +30,7 @@ def test_individual_files( webapp, webdriver ):
assert clipboard != "" assert clipboard != ""
# upload a new template # upload a new template
fname = template_id + ".j2" fname = template_id + ".j2"
set_stored_msg( "template_pack_persistence", set_stored_msg( "_template_pack_persistence_",
"{} | {}".format( fname, "UPLOADED TEMPLATE" ) "{} | {}".format( fname, "UPLOADED TEMPLATE" )
) )
select_menu_option( "template_pack" ) select_menu_option( "template_pack" )
@ -41,7 +41,7 @@ def test_individual_files( webapp, webdriver ):
for_each_template( test_template ) for_each_template( test_template )
# try uploading a template with an incorrect filename extension # 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" "filename.xyz | UPLOADED TEMPLATE"
) )
select_menu_option( "template_pack" ) select_menu_option( "template_pack" )
@ -49,7 +49,7 @@ def test_individual_files( webapp, webdriver ):
assert "Invalid template extension" in last_error_msg assert "Invalid template extension" in last_error_msg
# try uploading a template with an unknown filename # try uploading a template with an unknown filename
set_stored_msg( "template_pack_persistence", set_stored_msg( "_template_pack_persistence_",
"unknown.j2 | UPLOADED TEMPLATE" "unknown.j2 | UPLOADED TEMPLATE"
) )
select_menu_option( "template_pack" ) select_menu_option( "template_pack" )
@ -203,7 +203,7 @@ def _generate_snippet( template_id, orig_template_id ):
def _upload_template_pack( zip_data ): def _upload_template_pack( zip_data ):
"""Upload a template pack.""" """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") ) "{} | {}".format( "test.zip", base64.b64encode(zip_data).decode("ascii") )
) )
select_menu_option( "template_pack" ) select_menu_option( "template_pack" )

@ -6,6 +6,7 @@ import json
import time import time
import re import re
import pytest
from PyQt5.QtWidgets import QApplication from PyQt5.QtWidgets import QApplication
from selenium.webdriver.support.ui import Select from selenium.webdriver.support.ui import Select
from selenium.webdriver.common.keys import Keys from selenium.webdriver.common.keys import Keys
@ -316,11 +317,18 @@ def click_dialog_button( caption ):
# --------------------------------------------------------------------- # ---------------------------------------------------------------------
_pyqt_app = None
def get_clipboard() : def get_clipboard() :
"""Get the contents of the clipboard.""" """Get the contents of the clipboard."""
app = QApplication( [] ) #pylint: disable=unused-variable if pytest.config.option.no_clipboard: #pylint: disable=no-member
clipboard = QApplication.clipboard() return get_stored_msg( "_clipboard_" )
return clipboard.text() else:
global _pyqt_app
if _pyqt_app is None:
_pyqt_app = QApplication( [] )
clipboard = QApplication.clipboard()
return clipboard.text()
def wait_for( timeout, func ): def wait_for( timeout, func ):
"""Wait for a condition to become true.""" """Wait for a condition to become true."""

Loading…
Cancel
Save