Create attractive VASL scenarios, with loads of useful information embedded to assist with game play. https://vasl-templates.org
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 
vasl-templates/vasl_templates/webapp/tests/test_vo_reports.py

174 lines
6.8 KiB

""" Check the vehicle/ordnance reports. """
import os
import io
import shutil
import re
import pytest
import lxml.html
import lxml.etree
import tabulate
from vasl_templates.webapp.tests import pytest_options
import vasl_templates.webapp.tests.utils as test_utils
from vasl_templates.webapp.tests.utils import init_webapp, get_nationalities, find_child, wait_for
# ---------------------------------------------------------------------
@pytest.mark.skipif( pytest_options.short_tests, reason="--short-tests specified" )
def test_vo_reports( webapp, webdriver ): #pylint: disable=too-many-locals
"""Check the vehicle/ordnance reports."""
# initialize
webapp.control_tests \
.set_data_dir( "{REAL}" ) \
.set_vasl_version( "random", "{REAL}" )
init_webapp( webapp, webdriver )
# initialize
check_dir = os.path.join( os.path.split(__file__)[0], "fixtures/vo-reports/" )
save_dir = os.environ.get( "VO_REPORTS_SAVEDIR" ) # nb: define this to save the generated reports
if save_dir and os.path.isdir(save_dir):
shutil.rmtree( save_dir )
def fixup_capabilities( col, caption ):
"""Convert capability HTML to something a bit more readable."""
assert results[0][col] == caption
for i in range(1,len(results)):
results[i][col] = re.sub(
r"<sup>(.*?)</sup>",
lambda mo: "[{}]".format( mo.group(1) ),
results[i][col]
)
results[i][col] = re.sub(
r'<span class="brewup">(.*?)(\u2020.*)?</span>',
r"\1[brewup]\2",
results[i][col]
)
# check each vehicle/ordnance report
nationalities = list( get_nationalities( webapp ).keys() )
nationalities.extend( [ "allied-minor-common", "axis-minor-common", "landing-craft" ] )
failed = False
for nat in nationalities:
for vo_type in ["vehicles","ordnance"]:
# figure out which years we should generate reports for
# NOTE: The Americans and British are in K:FW, so we should really check 1950-53 for these as well,
# but there are only a few vehicles that have date-specific capabilities, so we don't bother testing
# for them here, and check those specific cases in test_kfw().
years = (1950,1953) if nat.startswith( "kfw-" ) else (1940,1945)
for year in range(years[0],years[1]+1):
# get the next report
if nat == "landing-craft" and vo_type == "ordnance":
continue
results = get_vo_report( webapp, webdriver, vo_type, nat, "ETO", year, 1 )
if nat in ( "burmese", "filipino", "partisan" ) \
or ( nat, vo_type ) in [ ("anzac","ordnance"), ("kfw-cpva","vehicles"), ("swedish","vehicles") ]:
assert not results
continue
# FUDGE! The "capabilities" and "notes" columns span 2 columns each,
# so we add dummy header columns to stop tabulate from getting confused :-/
assert results[0][-2] == "Notes"
results[0].insert( len(results[0])-2, "#" )
assert results[0][-4] == "Capabilities"
results[0].insert( len(results[0])-3, "(effective)" )
# fix up date-based capabilities
fixup_capabilities( -5, "Capabilities" )
fixup_capabilities( -4, "(effective)" )
fixup_capabilities( -3, "#" )
# convert the report to plain-text
buf = io.StringIO()
print( "=== {}/{}/{} ===".format( vo_type, nat, year ), file=buf )
print( "", file=buf )
print(
tabulate.tabulate( results, headers="firstrow" ),
file = buf
)
report = buf.getvalue()
# check if we should save the report
fname = "{}/{}/{}.txt".format( vo_type, nat, year )
if save_dir:
fname2 = os.path.join( save_dir, fname )
os.makedirs( os.path.split(fname2)[0], exist_ok=True )
with open( os.path.join(save_dir,fname2), "w", encoding="utf-8" ) as fp:
fp.write( report )
# check the report
fname = os.path.join( check_dir, fname )
with open( fname, "r", encoding="utf-8" ) as fp:
if fp.read() != report:
if save_dir:
print( "FAILED:", fname )
failed = True
else:
assert False, "Report mismatch: {}".format( fname )
assert not failed
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
def get_vo_report( webapp, webdriver,
vo_type, nat, theater, year, month,
name=None, merge_common=False
): #pylint: disable=too-many-arguments,too-many-locals
"""Get a vehicle/ordnance report.
NOTE: We can't get the V/O report to return its results as, say, plain-text, for easy checking,
since it's all done in Javascript, asynchronously i.e. we need something that will wait until
the results are ready i.e. Selenium, not wget :-/
"""
# nb: in case the caller hasn't called init_webapp()
test_utils._webdriver = webdriver #pylint: disable=protected-access
# initialize
url = webapp.url_for( "get_vo_report", vo_type=vo_type, nat=nat, theater=theater, year=year, month=month )
assert "?" in url
if name:
url += "&name={}".format( name )
if merge_common:
url += "&merge_common=1"
webdriver.get( url )
wait_for( 2, lambda: find_child("#results").is_displayed() )
# parse the report
results = _parse_report( webdriver.page_source )
return results
def _parse_report( buf ):
"""Parse a vehicle/ordnance report."""
def tidy( cell ):
"""Tidy up a cell value."""
val = lxml.etree.tostring( cell ).decode( "utf-8" ) #pylint: disable=c-extension-no-member
if val in ("<td/>","<th/>"):
return ""
mo = re.search( r"^<(th|td).*?>(.*)</\1>$", val )
val = mo.group(2)
if val == "<small><em>n/a</em></small>":
return "n/a"
val = re.sub( '<span class="val">(.*?)</span>', r"\1", val )
val = val.replace( "&#8224;", "\u2020" ).replace( "&#174;", "\u00ae" )
val = val.replace( "&#10003;", "yes" )
return val
# unload the results
# NOTE: Getting each table cell via Selenium is insanely slow - we parse the HTML manually :-/
results = []
doc = lxml.html.fromstring( buf )
for row in doc.xpath( "//div[@id='results']//table//tr" ):
tag = "td" if results else "th"
cells = row.xpath( ".//{}".format( tag ) )
results.append( list( tidy(c) for c in cells ) )
return results