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_vehicles_ordnance.py

797 lines
32 KiB

""" Test generating vehicle/ordnance snippets. """
import os
import re
import json
import pytest
from selenium.webdriver.common.action_chains import ActionChains
from selenium.webdriver.common.keys import Keys
from vasl_templates.webapp.tests import pytest_options
from vasl_templates.webapp.tests.test_scenario_persistence import load_scenario, save_scenario
from vasl_templates.webapp.tests.utils import \
init_webapp, get_nationalities, select_tab, set_template_params, find_child, find_children, \
wait_for_clipboard, click_dialog_button, select_menu_option, set_player, \
set_stored_msg_marker, get_stored_msg, get_sortable_vo_names
from vasl_templates.webapp.config.constants import DATA_DIR
# ---------------------------------------------------------------------
def test_crud( webapp, webdriver ):
"""Test basic create/read/update/delete of vehicles/ordnance."""
# initialize
init_webapp( webapp, webdriver )
# initialize
_expected = {
("vehicles",1): [], ("ordnance",1): [],
("vehicles",2): [], ("ordnance",2): []
}
_width = {
("vehicles",1): None, ("ordnance",1): None,
("vehicles",2): None, ("ordnance",2): None
}
def _add_vo( vo_type, player_no, name ):
"""Add a vehicle/ordnance."""
# check the hint
select_tab( "ob{}".format( player_no ) )
_check_hint( vo_type, player_no )
# add the vehicle/ordnance
add_vo( webdriver, vo_type, player_no, name )
_expected[ (vo_type,player_no) ].append( name )
# check the snippet and hint
_check_snippet( vo_type, player_no )
_check_hint( vo_type, player_no )
def _delete_vo( vo_type, player_no, name, webdriver ):
"""Delete a vehicle/ordnance."""
# check the hint
select_tab( "ob{}".format( player_no ) )
_check_hint( vo_type, player_no )
# delete the vehicle/ordnance
delete_vo( vo_type, player_no, name, webdriver )
_expected[ (vo_type,player_no) ].remove( name )
# check the snippet and hint
_check_snippet( vo_type, player_no )
_check_hint( vo_type, player_no )
def _set_width( vo_type, player_no, width ):
"""Set the snippet width."""
select_tab( "ob{}".format( player_no ) )
elem = find_child( "input[name='OB_{}_WIDTH_{}']".format( vo_type.upper(), player_no ) )
elem.clear()
if width is not None:
elem.send_keys( str(width) )
_width[ (vo_type,player_no) ] = width
def _check_snippet( vo_type, player_no ):
"""Check the generated vehicle/ordnance snippet."""
# check the snippet
select_tab( "ob{}".format( player_no ) )
btn = find_child( "button[data-id='ob_{}_{}']".format( vo_type, player_no ) )
btn.click()
def reformat( clipboard ): #pylint: disable=missing-docstring
return [
mo.group(1)
for mo in re.finditer( r"^\[\*\] (.*):" , clipboard, re.MULTILINE )
]
clipboard = wait_for_clipboard( 2, _expected[(vo_type,player_no)], transform=reformat )
# check the snippet width
expected = _width[ (vo_type,player_no) ]
mo = re.search(
r"width={}$".format( expected if expected else "" ),
clipboard,
re.MULTILINE
)
assert mo
def _check_hint( vo_type, player_no ):
"""Check the hint visibility."""
hint = find_child( "#ob_{}-hint_{}".format( vo_type, player_no ) )
expected = "none" if _expected[(vo_type,player_no)] else "block"
assert hint.value_of_css_property("display") == expected
def do_test( vo_type ):
"""Run the test."""
vo_type0 = vo_type[:-1] if vo_type.endswith("s") else vo_type
# add a German vehicle/ordnance
_add_vo( vo_type, 1, "a german {}".format(vo_type0) )
# generate a Russian vehicle/ordnance snippet
_check_snippet( vo_type, 2 )
# add a Russian vehicle/ordnance
_add_vo( vo_type, 2, "another russian {}".format(vo_type0) )
# go back and check the German snippet again
_check_snippet( vo_type, 1 )
# add another Russian vehicle/ordnance
_set_width( vo_type, 2, "200px" )
_add_vo( vo_type, 2, "name only" )
# delete the German vehicle/ordnance
_set_width( vo_type, 1, "100px" )
_delete_vo( vo_type, 1, "a german {}".format(vo_type0), webdriver )
_set_width( vo_type, 1, None )
_check_snippet( vo_type, 1 )
# go back and check the Russian snippet again
_check_snippet( vo_type, 2 )
# delete the Russian vehicles/ordnance
_delete_vo( vo_type, 2, "another russian {}".format(vo_type0), webdriver )
_set_width( vo_type, 2, None )
_delete_vo( vo_type, 2, "name only", webdriver )
# check the final state
assert not _expected[ (vo_type,1) ]
assert not _expected[ (vo_type,2) ]
# do the test
do_test( "vehicles" )
do_test( "ordnance" )
# ---------------------------------------------------------------------
def test_snippets( webapp, webdriver ):
"""Test vehicle/ordnance snippet generation in detail."""
# initialize
init_webapp( webapp, webdriver )
def do_test( vo_type ):
"""Run the test."""
vo_type0 = vo_type[:-1] if vo_type.endswith("s") else vo_type
# test a full example
add_vo( webdriver, vo_type, 1, "a german {}".format(vo_type0) )
btn = find_child( "button[data-id='ob_{}_1']".format( vo_type ) )
btn.click()
caps = '"XYZ" "IR" "A1" "H2"'
if vo_type == "vehicles":
caps += ' "CS 5"'
expected = [
'[German] ; width=',
'[*] a german {}: #=1'.format( vo_type0 ),
'- notes: "A" "B†"',
'- capabilities: {}'.format( caps ),
'- raw capabilities: {}'.format( caps ),
]
wait_for_clipboard( 2, "\n".join(expected) )
delete_vo( vo_type, 1, "a german {}".format(vo_type0), webdriver )
# test a partial example
add_vo( webdriver, vo_type, 1, "another german {}".format(vo_type0) )
btn = find_child( "button[data-id='ob_{}_1']".format( vo_type ) )
btn.click()
caps = '"XYZ"'
if vo_type == "vehicles":
caps += ' "<span class="brewup">cs 4</span>"'
expected = [
'[German] ; width=',
'[*] another german {}: #=2'.format( vo_type0 ),
'- capabilities: {}'.format( caps ),
'- raw capabilities: {}'.format( caps ),
]
if vo_type == "vehicles":
expected.insert( 2, '- notes: "<s>b</s>" "C"' )
wait_for_clipboard( 2, "\n".join(expected) )
delete_vo( vo_type, 1, "another german {}".format(vo_type0), webdriver )
# test a minimal example
add_vo( webdriver, vo_type, 1, "name only" )
btn = find_child( "button[data-id='ob_{}_1']".format( vo_type ) )
btn.click()
expected = [
'[German] ; width=',
'[*] name only: #=',
'- capabilities:',
'- raw capabilities:',
]
wait_for_clipboard( 2, "\n".join(expected) )
# do the test
set_player( 1, "german" )
do_test( "vehicles" )
do_test( "ordnance" )
# ---------------------------------------------------------------------
def test_variable_capabilities( webapp, webdriver ):
"""Test date-based variable capabilities."""
# initialize
init_webapp( webapp, webdriver )
# add a vehicle
add_vo( webdriver, "vehicles", 2, "Churchill III(b)" )
# change the scenario date and check the generated snippet
vehicles2 = find_child( "button.generate[data-id='ob_vehicles_2']" )
def do_test( month, year, expected ):
"""Set the date and check the vehicle snippet."""
select_tab( "scenario" )
set_template_params( { "SCENARIO_DATE": "{:02d}/01/{}".format(month,year) } )
select_tab( "ob2" )
vehicles2.click()
def reformat( clipboard ): #pylint: disable=missing-docstring
mo = re.search( r"^- capabilities: (.*)$", clipboard, re.MULTILINE )
return mo.group( 1 )
wait_for_clipboard( 2, expected, transform=reformat )
do_test( 1, 1940, '"sM8\u2020" "CS 7"' )
do_test( 1, 1943, '"sM8\u2020" "CS 7"' )
do_test( 2, 1943, '"HE7\u2020" "sM8\u2020" "CS 7"' )
do_test( 12, 1943, '"HE7\u2020" "sM8\u2020" "CS 7"' )
do_test( 1, 1944, '"HE8\u2020" "sD6" "sM8\u2020" "CS 7"' )
do_test( 5, 1944, '"HE8\u2020" "sD6" "sM8\u2020" "CS 7"' )
do_test( 6, 1944, '"D6\u2020" "HE8\u2020" "sD6" "sM8\u2020" "CS 7"' )
do_test( 12, 1944, '"D6\u2020" "HE8\u2020" "sD6" "sM8\u2020" "CS 7"' )
do_test( 1, 1945, '"D7\u2020" "HE8\u2020" "sD6" "sM8\u2020" "CS 7"' )
do_test( 12, 1945, '"D7\u2020" "HE8\u2020" "sD6" "sM8\u2020" "CS 7"' )
do_test( 1, 1946, '"HE8\u2020" "sD6" "sM8\u2020" "CS 7"' )
# ---------------------------------------------------------------------
def test_html_names( webapp, webdriver ):
"""Test handling of vehicles/ordnance that have HTML in their name."""
# initialize
webapp.control_tests.set_data_dir( "{REAL}" )
init_webapp( webapp, webdriver )
def get_available_ivfs():
"""Get the PzKw IVF's available for selection."""
entries = find_children( "#select-vo .select2-results li" )
entries = [ e.text for e in entries ]
return [ e for e in entries if "IVF" in e ]
# start to add a vehicle - make sure the two PzKw IVF's are available
set_player( 1, "german" )
select_tab( "ob1" )
add_vehicle_btn = find_child( "#ob_vehicles-add_1" )
add_vehicle_btn.click()
assert get_available_ivfs() == [ "PzKpfw IVF1 (MT)", "PzKpfw IVF2 (MT)" ]
# add the PzKw IVF2
elem = find_child( ".ui-dialog .select2-search__field" )
elem.send_keys( "IVF2" )
elem.send_keys( Keys.RETURN )
# make sure it was added to the player's OB
vehicles_sortable = find_child( "#ob_vehicles-sortable_1" )
assert get_sortable_vo_names( vehicles_sortable ) == [ "PzKpfw IVF2" ]
# start to add another vehicle - make sure both PzKw IVF's are still available
add_vehicle_btn.click()
assert get_available_ivfs() == [ "PzKpfw IVF1 (MT)", "PzKpfw IVF2 (MT)" ]
# add the PzKw IVF1
elem = find_child( ".ui-dialog .select2-search__field" )
elem.send_keys( "IVF1" )
elem.send_keys( Keys.RETURN )
# make sure it was added to the player's OB
assert get_sortable_vo_names( vehicles_sortable ) == [ "PzKpfw IVF2", "PzKpfw IVF1" ]
# start to add another vehicle - make sure both PzKw IVF's are still available
add_vehicle_btn.click()
assert get_available_ivfs() == [ "PzKpfw IVF1 (MT)", "PzKpfw IVF2 (MT)" ]
elem = find_child( ".ui-dialog .select2-search__field" )
elem.send_keys( Keys.ESCAPE )
# delete the PzKw IVF2
delete_vo( "vehicles", 1, "PzKpfw IVF2" , webdriver )
# start to add another vehicle - make sure both PzKw IVF's are still available
add_vehicle_btn.click()
assert get_available_ivfs() == [ "PzKpfw IVF1 (MT)", "PzKpfw IVF2 (MT)" ]
# ---------------------------------------------------------------------
def test_duplicate_vo_entries( webapp, webdriver ):
"""Test adding duplicate vehicles/ordnance."""
# initialize
init_webapp( webapp, webdriver )
set_player( 1, "german" )
select_tab( "ob1" )
def get_available_vo_entries():
"""Get the available vehicles/ordnance for selection."""
entries = find_children( "#select-vo .select2-results li" )
return [ e.text for e in entries ]
def do_test( vo_type, vo_name ): #pylint: disable=missing-docstring
# start to add a vehicle/ordnance
add_btn = find_child( "#ob_" + vo_type + "-add_1" )
add_btn.click()
assert vo_name in get_available_vo_entries()
# add the vehicle/ordnance
elem = find_child( ".ui-dialog .select2-search__field" )
elem.send_keys( vo_name )
elem.send_keys( Keys.RETURN )
# make sure it was added to the player's OB
sortable = find_child( "#ob_" + vo_type + "-sortable_1" )
assert get_sortable_vo_names( sortable ) == [ vo_name ]
# add the vehicle/ordnance, dismiss the warning
add_btn.click()
elem = find_child( ".ui-dialog .select2-search__field" )
elem.send_keys( vo_name )
elem.send_keys( Keys.RETURN )
elem = find_child( "#ask" )
assert "already in the OB" in elem.text
click_dialog_button( "Cancel" )
click_dialog_button( "Cancel" )
# make sure the player's OB is unchanged
assert get_sortable_vo_names( sortable ) == [ vo_name ]
# add the vehicle/ordnance, accept the warning
add_btn.click()
elem = find_child( ".ui-dialog .select2-search__field" )
elem.send_keys( vo_name )
elem.send_keys( Keys.RETURN )
elem = find_child( "#ask" )
assert "already in the OB" in elem.text
click_dialog_button( "OK" )
# make sure the vehicle/ordnance was added to the player's OB
assert get_sortable_vo_names( sortable ) == [ vo_name, vo_name ]
# do the test
do_test( "vehicles", "a german vehicle" )
do_test( "ordnance", "name only" )
# ---------------------------------------------------------------------
@pytest.mark.skipif( pytest_options.short_tests, reason="--short-tests specified" )
def test_common_vo( webapp, webdriver ): #pylint: disable=too-many-locals
"""Test loading of common vehicles/ordnance and landing craft."""
# initialize
webapp.control_tests.set_data_dir( "{REAL}" )
init_webapp( webapp, webdriver )
# initialize
ALLIED_MINOR = [ "belgian", "danish", "dutch", "greek", "polish", "yugoslavian" ]
AXIS_MINOR = [ "bulgarian", "croatian", "hungarian", "romanian", "slovakian" ]
# get the common vehicles/ordnance
def get_common_vo( fname ):
"""Get the vehicle/ordnance information from the specified file."""
fname = os.path.join( DATA_DIR, fname )
with open( fname, "r", encoding="utf-8" ) as fp:
data = json.load( fp )
def get_gpid( val ): #pylint: disable=missing-docstring
if isinstance( val, list ):
val = val[0]
assert isinstance(val,int) or val is None
return val
return [ ( vo["name"], get_gpid(vo["gpid"]) ) for vo in data ]
common_vo = {
"vehicles": {
"allied": get_common_vo( "vehicles/allied-minor/common.json" ),
"axis": get_common_vo( "vehicles/axis-minor/common.json" ),
},
"ordnance": {
"allied": get_common_vo( "ordnance/allied-minor/common.json" ),
"axis": get_common_vo( "ordnance/axis-minor/common.json" ),
},
}
landing_craft = get_common_vo( "vehicles/landing-craft.json" )
tidy_vo_name_regex = re.compile( r" \([A-Za-z]+\)$" ) # nb: removes the trailing vehicle/ordnance type
gpid_regex = re.compile( r"/counter/(\d+)/front" )
def get_vo_entry( elem ):
"""Get the vehicle/ordnance information from the Selenium element."""
vo_name = tidy_vo_name_regex.sub( "", elem.text )
image_url = find_child( "img", elem ).get_attribute( "src" )
mo = gpid_regex.search( image_url )
return ( vo_name, int(mo.group(1)) if mo else None )
def is_valid_vo_entry( vo_entry ):
"""Check if a V/O entry is valid."""
return isinstance( vo_entry, tuple ) and len(vo_entry) == 2 \
and isinstance( vo_entry[0], str ) \
and isinstance( vo_entry[1], (int,type(None)) )
def is_same_vo( lhs, rhs ):
"""Check if two V/O entries are the same."""
assert is_valid_vo_entry(lhs) and is_valid_vo_entry(rhs)
return lhs == rhs
def is_vo_entry_in_list( vo_entry, vo_entries ):
"""Check if a V/O entry appears in a list of V/O entries."""
assert is_valid_vo_entry( vo_entry )
return any( is_same_vo(vo_entry,e) for e in vo_entries )
# check the vehicles/ordnance for each nationality
nationalities = get_nationalities( webapp )
for nat in nationalities: #pylint: disable=too-many-nested-blocks
# select the next nationality
set_player( 1, nat )
select_tab( "ob1" )
for vo_type in ("vehicles","ordnance"):
# check if the nationality has any vehicles/ordnance
elem = find_child( "#ob_{}-add_1".format( vo_type ) )
if nat in ["thai","indonesian","anzac","burmese","filipino","partisan"]:
assert not elem.is_displayed()
continue
if (nat, vo_type) in [ ("kfw-cpva","vehicles"), ("swedish","vehicles") ]:
assert not elem.is_displayed()
continue
elem.click()
# get the vehicles/ordnance
vo_entries = find_children( "#select-vo .select2-results li" )
vo_entries = [ get_vo_entry(e) for e in vo_entries ]
click_dialog_button( "Cancel" )
# check that the common vehicles/ordnance are present/absent
if nat in ALLIED_MINOR:
assert all(
is_vo_entry_in_list( vo_entry, vo_entries )
for vo_entry in common_vo[vo_type]["allied"]
)
elif nat in AXIS_MINOR:
assert all(
is_vo_entry_in_list( vo_entry, vo_entries )
for vo_entry in common_vo[vo_type]["axis"]
)
else:
assert all(
not is_vo_entry_in_list( vo_entry, vo_entries )
for vo_entry in common_vo[vo_type]["allied"]
)
assert all(
not is_vo_entry_in_list( vo_entry, vo_entries )
for vo_entry in common_vo[vo_type]["axis"]
)
# check that the landing craft are present/absent
if vo_type == "vehicles":
if nat in ("british","american"):
for vo_entry in landing_craft:
if vo_entry[0] in ("Daihatsu","Shohatsu"):
assert not is_vo_entry_in_list( vo_entry, vo_entries )
else:
assert is_vo_entry_in_list( vo_entry, vo_entries )
elif nat == "japanese":
for vo_entry in landing_craft:
if vo_entry[0] in ("Daihatsu","Shohatsu"):
assert is_vo_entry_in_list( vo_entry, vo_entries )
else:
assert not is_vo_entry_in_list( vo_entry, vo_entries )
else:
assert all(
not is_vo_entry_in_list( vo_entry, vo_entries )
for vo_entry in landing_craft
)
# ---------------------------------------------------------------------
def test_vo_images( webapp, webdriver ): #pylint: disable=too-many-statements
"""Test handling of vehicles/ordnance that have multiple images."""
# initialize
webapp.control_tests \
.set_data_dir( "{REAL}" ) \
.set_vasl_version( "random", None )
init_webapp( webapp, webdriver, scenario_persistence=1 )
vehicle_sortables = [ find_child( "#ob_vehicles-sortable_1" ), find_child( "#ob_vehicles-sortable_2" ) ]
def check_sortable2_entries( player_no, expected ):
"""Check the settings on the player's vehicles."""
entries = find_children( "li", vehicle_sortables[player_no-1] )
for i,entry in enumerate(entries):
# check the displayed image
elem = find_child( "img", entry )
assert elem.get_attribute( "src" ).endswith( expected[i][0] )
# check the attached data
data = webdriver.execute_script( "return $(arguments[0]).data('sortable2-data')", entry )
assert data["vo_entry"]["id"] == expected[i][1]
assert data["vo_image_id"] == expected[i][2]
def check_save_scenario( player_no, expected ):
"""Check the vo_entry and vo_image_id fields are saved correctly."""
data = save_scenario()
assert data[ "OB_VEHICLES_{}".format(player_no) ] == expected
return data
# start to add a PzKw VIB
set_player( 1, "german" )
select_tab( "ob1" )
add_vehicle_btn = find_child( "#ob_vehicles-add_1" )
add_vehicle_btn.click()
search_field = find_child( ".ui-dialog .select2-search__field" )
search_field.send_keys( "VIB" )
# make sure there is only 1 image available
elem = find_child( "#select-vo .select2-results li img[class='vasl-image']" )
assert elem.get_attribute( "src" ).endswith( "/counter/2602/front" )
vo_images = webdriver.execute_script( "return $(arguments[0]).data('vo-images')", elem )
assert vo_images is None
assert not find_child( "#select-vo .select2-results li input.select-vo-image" )
# add the PzKw VIB, make sure the sortable2 entry has its data set correctly
search_field.send_keys( Keys.RETURN )
check_sortable2_entries( 1, [
( "/counter/2602/front", "ge/v:035", None )
] )
# check that the vehicles are saved correctly
check_save_scenario( 1, [
{ "id": "ge/v:035", "name": "PzKpfw VIB", "seq_id": 1 },
] )
# start to add a PzKw IVH (this has multiple GPID's)
add_vehicle_btn.click()
search_field = find_child( ".ui-dialog .select2-search__field" )
search_field.send_keys( "IVH" )
# make sure multiple images are available
elem = find_child( "#select-vo .select2-results li img[class='vasl-image']" )
assert elem.get_attribute( "src" ).endswith( "/counter/2584/front" )
vo_images = webdriver.execute_script( "return $(arguments[0]).data('vo-images')", elem )
assert vo_images == [ [2584,0], [2586,0], [2807,0], [2809,0] ]
assert find_child( "#select-vo .select2-results li input.select-vo-image" )
# add the PzKw IVH, make sure the sortable2 entry has its data set correctly
search_field.send_keys( Keys.RETURN )
check_sortable2_entries( 1, [
( "/counter/2602/front", "ge/v:035", None ),
( "/counter/2584/front", "ge/v:027", None ) # nb: there is no V/O image ID if it's not necessary
] )
# check that the vehicles are saved correctly
check_save_scenario( 1, [
{ "id": "ge/v:035", "name": "PzKpfw VIB", "seq_id": 1 },
{ "id": "ge/v:027", "name": "PzKpfw IVH", "seq_id": 2 }, # nb: there is no V/O image ID if it's not necessary
] )
# delete the PzKw IVH
delete_vo( "vehicles", 1, "PzKpfw IVH", webdriver )
# add the PzKw IVH, with a different image, make sure the sortable2 entry has its data set correctly
add_vehicle_btn.click()
search_field = find_child( ".ui-dialog .select2-search__field" )
search_field.send_keys( "IVH" )
elem = find_child( "#select-vo .select2-results li img[class='vasl-image']" )
assert elem.get_attribute( "src" ).endswith( "/counter/2584/front" )
btn = find_child( "#select-vo .select2-results li input.select-vo-image" )
btn.click()
images = find_children( ".ui-dialog.select-vo-image .vo-images img" )
assert len(images) == 4
images[2].click()
check_sortable2_entries( 1, [
( "/counter/2602/front", "ge/v:035", None ),
( "/counter/2807/front/0", "ge/v:027", [2807,0] )
] )
# check that the vehicles are saved correctly
check_save_scenario( 1, [
{ "id": "ge/v:035", "name": "PzKpfw VIB", "seq_id": 1 },
{ "id": "ge/v:027", "image_id": "2807/0", "name": "PzKpfw IVH", "seq_id": 2 },
] )
# set the British as player 2
set_player( 2, "british" )
# start to add a 2pdr Portee (this has multiple images for a single GPID)
select_tab( "ob2" )
add_vehicle_btn = find_child( "#ob_vehicles-add_2" )
add_vehicle_btn.click()
search_field = find_child( ".ui-dialog .select2-search__field" )
search_field.send_keys( "2pdr" )
# make sure multiple images are available
elem = find_child( "#select-vo .select2-results li img[class='vasl-image']" )
assert elem.get_attribute( "src" ).endswith( "/counter/1555/front" )
vo_images = webdriver.execute_script( "return $(arguments[0]).data('vo-images')", elem )
assert vo_images == [ [1555,0], [1555,1] ]
assert find_child( "#select-vo .select2-results li input.select-vo-image" )
# add the 2pdr Portee, make sure the sortable2 entry has its data set correctly
search_field.send_keys( Keys.RETURN )
check_sortable2_entries( 2, [
( "/counter/1555/front", "br/v:115", None ) # nb: there is no V/O image ID if it's not necessary
] )
# check that the vehicles are saved correctly
check_save_scenario( 2, [
{ "id": "br/v:115", "name": "2pdr Portee", "seq_id": 1 }, # nb: there is no V/O image ID if it's not necessary
] )
# delete the 2pdr Portee
delete_vo( "vehicles", 2, "2pdr Portee", webdriver )
# add the 2pdr Portee, with a different image, make sure the sortable2 entry has its data set correctly
add_vehicle_btn.click()
search_field = find_child( ".ui-dialog .select2-search__field" )
search_field.send_keys( "2pdr" )
elem = find_child( "#select-vo .select2-results li img[class='vasl-image']" )
assert elem.get_attribute( "src" ).endswith( "/counter/1555/front" )
btn = find_child( "#select-vo .select2-results li input.select-vo-image" )
btn.click()
images = find_children( ".ui-dialog.select-vo-image .vo-images img" )
assert len(images) == 2
images[1].click()
check_sortable2_entries( 2, [
( "/counter/1555/front/1", "br/v:115", [1555,1] )
] )
# check that the vehicles are saved correctly
saved_scenario = check_save_scenario( 2, [
{ "id": "br/v:115", "image_id": "1555/1", "name": "2pdr Portee", "seq_id": 1 },
] )
# reset the scenario
select_menu_option( "new_scenario" )
check_sortable2_entries( 1, [] )
check_sortable2_entries( 2, [] )
# load the last saved scenario, make sure the correct images are displayed
load_scenario( saved_scenario )
check_sortable2_entries( 1, [
( "/counter/2602/front", "ge/v:035", None ),
( "/counter/2807/front/0", "ge/v:027", ["2807",0] )
] )
check_sortable2_entries( 2, [
( "/counter/1555/front/1", "br/v:115", ["1555",1] )
] )
# ---------------------------------------------------------------------
def test_change_vo_image( webapp, webdriver ):
"""Test changing a V/O image."""
# initialize
webapp.control_tests \
.set_data_dir( "{REAL}" ) \
.set_vasl_version( "random", None )
init_webapp( webapp, webdriver, scenario_persistence=1 )
# add an ISU-152
set_player( 2, "russian" )
add_vo( webdriver, "vehicles", 2, "ISU-152" )
# save the scenario
saved_scenario = save_scenario()
assert saved_scenario["OB_VEHICLES_2"] == [ { "id": "ru/v:049", "name": "ISU-152", "seq_id": 1 } ]
# change the vehicle's image
vehicles_sortable = find_child( "#ob_vehicles-sortable_2" )
elems = find_children( "li", vehicles_sortable )
assert len(elems) == 1
ActionChains(webdriver).double_click( elems[0] ).perform()
img = find_child( "#edit-vo img.vasl-image" )
assert img.get_attribute( "src" ).endswith( "/counter/657/front" )
btn = find_child( "#edit-vo input.select-vo-image" )
btn.click()
images = find_children( ".ui-dialog.select-vo-image .vo-images img" )
assert len(images) == 2
images[1].click()
assert img.get_attribute( "src" ).endswith( "/counter/659/front/0" )
click_dialog_button( "OK" )
elems = find_children( "img.vasl-image", vehicles_sortable )
assert len(elems) == 1
assert elems[0].get_attribute( "src" ).endswith( "/counter/659/front/0" )
# save the scenario
saved_scenario = save_scenario()
assert saved_scenario["OB_VEHICLES_2"] == [
{ "id": "ru/v:049", "image_id": "659/0", "name": "ISU-152", "seq_id": 1 }
]
# reload the scenario, and check the vehicle's image
select_menu_option( "new_scenario" )
load_scenario( saved_scenario )
select_tab( "ob2" )
elems = find_children( "img.vasl-image", vehicles_sortable )
assert len(elems) == 1
assert elems[0].get_attribute( "src" ).endswith( "/counter/659/front/0" )
# change the vehicle's image back to the default
elems = find_children( "li", vehicles_sortable )
assert len(elems) == 1
ActionChains(webdriver).double_click( elems[0] ).perform()
img = find_child( "#edit-vo img.vasl-image" )
assert img.get_attribute( "src" ).endswith( "/counter/659/front/0" )
btn = find_child( "#edit-vo input.select-vo-image" )
btn.click()
images = find_children( ".ui-dialog.select-vo-image .vo-images img" )
assert len(images) == 2
images[0].click()
assert img.get_attribute( "src" ).endswith( "/counter/657/front/0" )
click_dialog_button( "OK" )
elems = find_children( "img.vasl-image", vehicles_sortable )
assert len(elems) == 1
assert elems[0].get_attribute( "src" ).endswith( "/counter/657/front/0" )
# save the scenario
saved_scenario = save_scenario()
assert saved_scenario["OB_VEHICLES_2"] == [
{ "id": "ru/v:049", "image_id": "657/0", "name": "ISU-152", "seq_id": 1 }
]
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
def test_change_vo_image2( webapp, webdriver ):
"""Test changing the image for a V/O that has no alternative images."""
# initialize
webapp.control_tests.set_data_dir( "{REAL}" )
init_webapp( webapp, webdriver, scenario_persistence=1 )
# add an 107mm GVPM
set_player( 2, "russian" )
add_vo( webdriver, "ordnance", 2, "107mm GVPM obr. 38" )
# make sure the "change image" button is not present
ordnance_sortable = find_child( "#ob_ordnance-sortable_2" )
elems = find_children( "li", ordnance_sortable )
assert len(elems) == 1
ActionChains(webdriver).double_click( elems[0] ).perform()
btn = find_child( "#edit-vo input.select-vo-image" )
assert btn is None
# ---------------------------------------------------------------------
def test_invalid_vo_image_ids( webapp, webdriver ):
"""Test loading scenarios that contain invalid V/O image ID's."""
# initialize
init_webapp( webapp, webdriver, scenario_persistence=1 )
# test each save file
dname = os.path.join( os.path.split(__file__)[0], "fixtures/invalid-vo-image-ids" )
for root,_,fnames in os.walk(dname):
for fname in fnames:
fname = os.path.join( root, fname )
if os.path.splitext( fname )[1] != ".json":
continue
# load the next scenario, make sure a warning was issued for the V/O image ID
with open( fname, "r", encoding="utf-8" ) as fp:
data = json.load( fp )
set_stored_msg_marker( "_last-warning_" )
load_scenario( data )
last_warning = get_stored_msg( "_last-warning_" )
assert "Invalid V/O image ID" in last_warning
# ---------------------------------------------------------------------
def add_vo( webdriver, vo_type, player_no, name ): #pylint: disable=unused-argument
"""Add a vehicle/ordnance."""
# add the vehicle/ordnance
select_tab( "ob{}".format( player_no ) )
elem = find_child( "#ob_{}-add_{}".format( vo_type, player_no ) )
elem.click()
# FUDGE! Locating the vehicle/ordnance by name and selecting it is finicky, I suspect
# because select2 is sensitive about where the mouse is, and we sometimes end up
# selecting the wrong item :-/ Selecting by name won't work if there are multiple items
# that start with the same thing, but that shouldn't be a problem.
dlg = find_child( "#select-vo" )
elem = find_child( "input", dlg )
elem.send_keys( name )
entries = find_children( ".select2-results li", dlg )
assert len(entries) == 1
click_dialog_button( "OK" )
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
def delete_vo( vo_type, player_no, name, webdriver ):
"""Delete a vehicle/ordnance."""
# delete the vehicle/ordnance
select_tab( "ob{}".format( player_no ) )
sortable = find_child( "#ob_{}-sortable_{}".format( vo_type, player_no ) )
elems = [
c for c in find_children( "li .vo-name", sortable )
if c.text == name
]
assert len(elems) == 1
elem = elems[0]
trash = find_child( "#ob_{}-trash_{}".format( vo_type, player_no ) )
ActionChains(webdriver).drag_and_drop( elem, trash ).perform()