-
+
diff --git a/vasl_templates/webapp/templates/turn-track-dialog.html b/vasl_templates/webapp/templates/turn-track-dialog.html
new file mode 100644
index 0000000..921fae2
--- /dev/null
+++ b/vasl_templates/webapp/templates/turn-track-dialog.html
@@ -0,0 +1,21 @@
+
+
+
+
+
+
+
+
Width:
+
Vertical
+
Swap players
+
+
+
+
+
+
+
+
diff --git a/vasl_templates/webapp/tests/fixtures/asl-scenario-archive.json b/vasl_templates/webapp/tests/fixtures/asl-scenario-archive.json
index bb13589..d22c208 100644
--- a/vasl_templates/webapp/tests/fixtures/asl-scenario-archive.json
+++ b/vasl_templates/webapp/tests/fixtures/asl-scenario-archive.json
@@ -12,7 +12,7 @@
"scen_date": "1945-12-31 00:00:00",
"theatre": "PTO",
"time_to_play": 1.25,
- "min_turns": "6", "max_turns": "6",
+ "min_turns": "4", "max_turns": "5",
"oba": "B", "night": "1", "deluxe": "1", "aslsk": "1",
"author": "Joe Author",
"pub_name": "ASL Journal",
diff --git a/vasl_templates/webapp/tests/fixtures/data/default-template-pack/turn_track.j2 b/vasl_templates/webapp/tests/fixtures/data/default-template-pack/turn_track.j2
new file mode 100644
index 0000000..43e1935
--- /dev/null
+++ b/vasl_templates/webapp/tests/fixtures/data/default-template-pack/turn_track.j2
@@ -0,0 +1,4 @@
+TURN TRACK:
+{% for row in TURN_TRACK_SQUARES %}
+{% for turnSquare in row %}[{{turnSquare}}] {%endfor%}
+{%endfor%}
diff --git a/vasl_templates/webapp/tests/fixtures/template-packs/full/turn_track.j2 b/vasl_templates/webapp/tests/fixtures/template-packs/full/turn_track.j2
new file mode 100644
index 0000000..f905247
--- /dev/null
+++ b/vasl_templates/webapp/tests/fixtures/template-packs/full/turn_track.j2
@@ -0,0 +1 @@
+Customized TURN_TRACK.
diff --git a/vasl_templates/webapp/tests/fixtures/template-packs/new-default/turn_track.j2 b/vasl_templates/webapp/tests/fixtures/template-packs/new-default/turn_track.j2
new file mode 100644
index 0000000..c4925a4
--- /dev/null
+++ b/vasl_templates/webapp/tests/fixtures/template-packs/new-default/turn_track.j2
@@ -0,0 +1 @@
+New default TURN_TRACK.
diff --git a/vasl_templates/webapp/tests/test_help.py b/vasl_templates/webapp/tests/test_help.py
index b11239d..bd3b314 100644
--- a/vasl_templates/webapp/tests/test_help.py
+++ b/vasl_templates/webapp/tests/test_help.py
@@ -1,7 +1,7 @@
""" Test the help page. """
from vasl_templates.webapp.tests.utils import \
- init_webapp, select_menu_option, find_child, find_children, wait_for, wait_for_elem
+ init_webapp, select_menu_option, find_children, wait_for, wait_for_elem, SwitchFrame
# ---------------------------------------------------------------------
@@ -28,10 +28,7 @@ def test_help( webapp, webdriver ):
assert "tabs-help" in get_tabs()
# check what's in the help iframe
- try:
-
- # switch to the frame
- webdriver.switch_to.frame( find_child( "#tabs-help iframe" ) )
+ with SwitchFrame( webdriver, "#tabs-help iframe" ):
# check that the content loaded OK
assert "everyone's favorite scenario" in webdriver.page_source
@@ -41,8 +38,3 @@ def test_help( webapp, webdriver ):
assert elem.is_displayed()
wait_for( 2, lambda: "GNU AFFERO GENERAL PUBLIC LICENSE" in webdriver.page_source )
assert "Version 3" in webdriver.page_source
-
- finally:
-
- # switch back to the main window
- webdriver.switch_to.default_content()
diff --git a/vasl_templates/webapp/tests/test_lfa.py b/vasl_templates/webapp/tests/test_lfa.py
index 43af3f5..21cdc1e 100644
--- a/vasl_templates/webapp/tests/test_lfa.py
+++ b/vasl_templates/webapp/tests/test_lfa.py
@@ -381,7 +381,8 @@ def test_hotness_report( webapp, webdriver ):
report = {}
for key in ( "2s", "12s", "snipers" ):
report[ key ] = unload_table(
- "//div[@class='hotness-popup']//table[@class='{}']//tr".format( key )
+ "//div[@class='hotness-popup']//table[@class='{}']/tbody".format( key ),
+ unload=True
)
return report
@@ -692,5 +693,6 @@ def _select_log_file( fname ):
def _unload_table( sel ):
"""Unload chart data from an HTML table."""
return unload_table(
- "//*[@class='{}']//table[@class='chart-data']//tr".format( sel )
+ "//*[@class='{}']//table[@class='chart-data']/tbody".format( sel ),
+ unload=True
)
diff --git a/vasl_templates/webapp/tests/test_national_capabilities.py b/vasl_templates/webapp/tests/test_national_capabilities.py
index 50f3a01..2b7b340 100644
--- a/vasl_templates/webapp/tests/test_national_capabilities.py
+++ b/vasl_templates/webapp/tests/test_national_capabilities.py
@@ -6,7 +6,7 @@ import io
import lxml.html
-from vasl_templates.webapp.tests.utils import init_webapp, get_nationalities, wait_for, find_child
+from vasl_templates.webapp.tests.utils import init_webapp, get_nationalities, SwitchFrame
# ---------------------------------------------------------------------
@@ -83,13 +83,8 @@ def _get_nat_caps( webapp, webdriver, nat, theater, year, month ): #pylint: disa
# get the snippet
url = webapp.url_for( "get_national_capabilities", nat=nat, theater=theater, year=year, month=month )
webdriver.get( url )
- iframe = find_child( "#results" )
- wait_for( 2, iframe.is_displayed )
- try:
- webdriver.switch_to.frame( iframe )
+ with SwitchFrame( webdriver, "#results" ):
buf = webdriver.page_source
- finally:
- webdriver.switch_to.default_content()
# check if there is anything
if "Not available." in buf:
diff --git a/vasl_templates/webapp/tests/test_scenario_search.py b/vasl_templates/webapp/tests/test_scenario_search.py
index 1a4e527..aaa6ced 100644
--- a/vasl_templates/webapp/tests/test_scenario_search.py
+++ b/vasl_templates/webapp/tests/test_scenario_search.py
@@ -14,6 +14,7 @@ from vasl_templates.webapp.tests.test_scenario_persistence import save_scenario,
from vasl_templates.webapp.tests.test_vassal import run_vassal_tests
from vasl_templates.webapp.tests.utils import init_webapp, select_tab, new_scenario, \
set_player, set_template_params, set_scenario_date, get_player_nat, get_theater, set_theater, \
+ get_turn_track_nturns, \
wait_for, wait_for_elem, find_child, find_children, get_css_classes, set_stored_msg, click_dialog_button
# ---------------------------------------------------------------------
@@ -31,7 +32,7 @@ def test_scenario_cards( webapp, webdriver ):
"scenario_name": "Full content scenario", "scenario_id": "FCS-1",
"scenario_url": "https://aslscenarioarchive.com/scenario.php?id=1",
"scenario_location": "Some place", "scenario_date": "31st December, 1945",
- "theater": "PTO", "turn_count": "6", "playing_time": "1\u00bc hours",
+ "theater": "PTO", "turn_count": "4-5", "playing_time": "1\u00bc hours",
"icons": [ "aslsk.png", "deluxe.png", "night.png", "oba.png" ],
"designer": "Joe Author",
"publication": "ASL Journal",
@@ -87,6 +88,7 @@ def test_import_scenario( webapp, webdriver ):
wait_for( 2, lambda: _check_scenario(
SCENARIO_NAME="Full content scenario", SCENARIO_ID="FCS-1",
SCENARIO_LOCATION="Some place",
+ SCENARIO_TURNS="5",
PLAYER_1="dutch", PLAYER_1_DESCRIPTION="1st Dutch Army",
PLAYER_2="romanian", PLAYER_2_DESCRIPTION="1st Romanian Army",
THEATER="PTO"
@@ -100,6 +102,7 @@ def test_import_scenario( webapp, webdriver ):
wait_for( 2, lambda: _check_scenario(
SCENARIO_NAME="Untitled scenario (#no-content)", SCENARIO_ID="",
SCENARIO_LOCATION="",
+ SCENARIO_TURNS="",
PLAYER_1="dutch", PLAYER_1_DESCRIPTION="",
PLAYER_2="romanian", PLAYER_2_DESCRIPTION="",
THEATER="ETO"
@@ -115,6 +118,8 @@ def _check_scenario( **kwargs ):
return False
if get_theater() != kwargs[ "THEATER" ]:
return False
+ if get_turn_track_nturns() != kwargs["SCENARIO_TURNS"]:
+ return False
return True
# ---------------------------------------------------------------------
diff --git a/vasl_templates/webapp/tests/test_snippets.py b/vasl_templates/webapp/tests/test_snippets.py
index 88e1039..7026d53 100644
--- a/vasl_templates/webapp/tests/test_snippets.py
+++ b/vasl_templates/webapp/tests/test_snippets.py
@@ -12,7 +12,7 @@ from vasl_templates.webapp.tests.utils import \
get_stored_msg, set_stored_msg_marker, find_child, find_children, adjust_html, \
for_each_template, add_simple_note, edit_simple_note, \
get_sortable_entry_count, generate_sortable_entry_snippet, drag_sortable_entry_to_trash, \
- new_scenario, set_scenario_date
+ new_scenario, set_scenario_date, set_turn_track_nturns
from vasl_templates.webapp.tests.test_scenario_persistence import load_scenario, load_scenario_params
# ---------------------------------------------------------------------
@@ -232,6 +232,7 @@ def test_edit_templates( webapp, webdriver ):
# initialize
webapp.control_tests.set_vo_notes_dir( "{TEST}" )
init_webapp( webapp, webdriver, edit_template_links=1 )
+ set_turn_track_nturns( "3" )
ob_setups = {
1: find_child( "#ob_setups-sortable_1" ),
2: find_child( "#ob_setups-sortable_2" )
diff --git a/vasl_templates/webapp/tests/test_template_packs.py b/vasl_templates/webapp/tests/test_template_packs.py
index 13c4dae..272ad78 100644
--- a/vasl_templates/webapp/tests/test_template_packs.py
+++ b/vasl_templates/webapp/tests/test_template_packs.py
@@ -11,7 +11,7 @@ from selenium.webdriver.common.by import By
from vasl_templates.webapp.utils import TempFile
from vasl_templates.webapp.tests.test_vehicles_ordnance import add_vo
from vasl_templates.webapp.tests.utils import \
- select_tab, select_menu_option, set_player, \
+ select_tab, select_menu_option, set_player, set_turn_track_nturns, \
wait_for_clipboard, get_stored_msg, set_stored_msg, set_stored_msg_marker,\
add_simple_note, for_each_template, find_child, find_children, wait_for, \
get_player_nat, get_droplist_vals_index, init_webapp, get_css_classes
@@ -26,6 +26,7 @@ def test_individual_files( webapp, webdriver ):
init_webapp( webapp, webdriver, template_pack_persistence=1 )
set_player( 1, "german" )
set_player( 2, "russian" )
+ set_turn_track_nturns( "3" )
# try uploading a customized version of each template
def test_template( template_id, orig_template_id ):
@@ -55,6 +56,7 @@ def test_zip_files( webapp, webdriver ):
init_webapp( webapp, webdriver, template_pack_persistence=1 )
set_player( 1, "german" )
set_player( 2, "russian" )
+ set_turn_track_nturns( "3" )
# upload a template pack that contains a full set of templates
zip_data = make_zip_from_files( "full" )
@@ -89,6 +91,7 @@ def test_new_default_template_pack( webapp, webdriver ):
.set_default_template_pack( "new-default/" ) \
.set_vo_notes_dir( "{TEST}" )
init_webapp( webapp, webdriver )
+ set_turn_track_nturns( "3" )
# check that the new templates are being used
_do_test_default_template_pack( webdriver )
@@ -104,6 +107,7 @@ def test_new_default_template_pack_zip( webapp, webdriver ):
.set_default_template_pack( zip_data ) \
.set_vo_notes_dir( "{TEST}" )
init_webapp( webapp, webdriver )
+ set_turn_track_nturns( "3" )
# check that the new templates are being used
_do_test_default_template_pack( webdriver )
diff --git a/vasl_templates/webapp/tests/test_turn_track.py b/vasl_templates/webapp/tests/test_turn_track.py
new file mode 100644
index 0000000..6513dea
--- /dev/null
+++ b/vasl_templates/webapp/tests/test_turn_track.py
@@ -0,0 +1,343 @@
+""" Test the turn track functionality. """
+
+from selenium.webdriver.support.ui import Select
+from selenium.webdriver.common.keys import Keys
+
+from vasl_templates.webapp.tests.utils import \
+ init_webapp, get_turn_track_nturns, set_turn_track_nturns, select_droplist_val, get_droplist_vals, \
+ SwitchFrame, unload_table, wait_for, wait_for_elem, wait_for_clipboard, find_child
+from vasl_templates.webapp.tests.test_scenario_persistence import load_scenario, save_scenario
+
+# ---------------------------------------------------------------------
+
+def test_turn_track_basic( webapp, webdriver ):
+ """Test basic turn track functionality."""
+
+ # initialize
+ webapp.control_tests.set_data_dir( "{REAL}" )
+ init_webapp( webapp, webdriver )
+
+ # check the initial state of the UI
+ assert get_turn_track_nturns() == ""
+ assert not find_child( "button#turn-track-settings" ).is_displayed()
+ assert not find_child( ".snippet-control[data-id='turn_track']" ).is_displayed()
+
+ # configure a number of turns
+ set_turn_track_nturns( 6 )
+ assert find_child( "button#turn-track-settings" ).is_displayed()
+ assert find_child( ".snippet-control[data-id='turn_track']" ).is_displayed()
+
+ # generate a snippet
+ assert _generate_turn_track_snippet( None ) == [
+ [ (1,None,None), (2,None,None), (3,None,None), (4,None,None), (5,None,None), (6,None,None) ]
+ ]
+
+# ---------------------------------------------------------------------
+
+def test_turn_track_controls( webapp, webdriver ):
+ """Test the basic controls for configuring the turn track."""
+
+ # initialize
+ webapp.control_tests.set_data_dir( "{REAL}" )
+ init_webapp( webapp, webdriver )
+
+ # show the turn track dialog
+ dlg = _show_turn_track_dialog( 6 )
+ with SwitchFrame( webdriver, "#turn-track-preview" ):
+ _click_reinf_flag( 1, 1 )
+ _click_reinf_flag( 2, 1 )
+ _click_reinf_flag( 2, 2 )
+ _click_reinf_flag( 3, 2 )
+
+ # change the width
+ _change_turn_track_width( dlg, 3 )
+ def check_for_width():
+ return _generate_turn_track_snippet( dlg ) == [
+ [ (1,"player1",None), (2,"player1","player2"), (3,None,"player2") ],
+ [ (4,None,None), (5,None,None), (6,None,None) ]
+ ]
+ wait_for( 2, check_for_width )
+
+ # swap the players
+ _swap_turn_track_players( dlg )
+ def check_for_swap_players():
+ return _generate_turn_track_snippet( dlg ) == [
+ [ (1,None,"player2"), (2,"player1","player2"), (3,"player1",None) ],
+ [ (4,None,None), (5,None,None), (6,None,None) ]
+ ]
+ wait_for( 2, check_for_swap_players )
+
+ # make the turn track vertical
+ _change_turn_track_direction( dlg )
+ def check_for_vertical():
+ return _generate_turn_track_snippet( dlg ) == [
+ [ (1,None,"player2"), (3,"player1",None), (5,None,None) ],
+ [ (2,"player1","player2"), (4,None,None), (6,None,None) ]
+ ]
+ wait_for( 2, check_for_vertical )
+
+ # reset the controls
+ find_child( "button.reset2" ).click()
+ ask = wait_for_elem( 2, ".ui-dialog.ask" )
+ find_child( "button.ok", ask ).click()
+ def check_for_reset():
+ return _generate_turn_track_snippet( dlg ) == [
+ [ (1,None,None), (2,None,None), (3,None,None), (4,None,None), (5,None,None), (6,None,None) ]
+ ]
+ wait_for( 2, check_for_reset )
+
+# ---------------------------------------------------------------------
+
+def test_turn_track_reinforcements( webapp, webdriver ):
+ """Test configuring reinforcements on the turn track."""
+
+ # initialize
+ webapp.control_tests.set_data_dir( "{REAL}" )
+ init_webapp( webapp, webdriver )
+
+ # show the turn track dialog
+ dlg = _show_turn_track_dialog( 6.5 )
+
+ # turn on some reinforcements, then check the snippet
+ with SwitchFrame( webdriver, "#turn-track-preview" ):
+ _click_reinf_flag( 2, 1 )
+ _click_reinf_flag( 3, 1 )
+ _click_reinf_flag( 3, 2 )
+ _click_reinf_flag( 7, 1 )
+ assert _generate_turn_track_snippet( dlg ) == [
+ [ (1,None,None), (2,"player1",None), (3,"player1","player2"),
+ (4,None,None), (5,None,None) , (6,None,None), (7,"player1",None)
+ ]
+ ]
+
+ # turn off some reinforcements, turn some on, then check the snippet
+ with SwitchFrame( webdriver, "#turn-track-preview" ):
+ _click_reinf_flag( 2, 2 )
+ _click_reinf_flag( 3, 1 )
+ _click_reinf_flag( 3, 2 )
+ _click_reinf_flag( 5, 2 )
+ _click_reinf_flag( 7, 1 )
+ assert _generate_turn_track_snippet( dlg ) == [
+ [ (1,None,None), (2,"player1","player2"), (3,None,None),
+ (4,None,None), (5,None,"player2") , (6,None,None), (7,None,None)
+ ]
+ ]
+
+# ---------------------------------------------------------------------
+
+def test_turn_track_persistence( webapp, webdriver ):
+ """Test saving and loading turn track settings."""
+
+ # initialize
+ webapp.control_tests.set_data_dir( "{REAL}" )
+ init_webapp( webapp, webdriver, scenario_persistence=1 )
+
+ # show the turn track dialog
+ load_scenario( {
+ "PLAYER_1": "japanese", "PLAYER_2": "american",
+ "TURN_TRACK": { "NTURNS": 6.5 },
+ } )
+ dlg = _show_turn_track_dialog( None )
+
+ # configure the turn track
+ with SwitchFrame( webdriver, "#turn-track-preview" ):
+ _click_reinf_flag( 1, 1 )
+ _click_reinf_flag( 2, 2 )
+ _click_reinf_flag( 3, 1 )
+ _click_reinf_flag( 3, 2 )
+ _change_turn_track_width( dlg, 4 )
+ _swap_turn_track_players( dlg )
+ _change_turn_track_direction( dlg )
+
+ # check the snippet
+ expected = [
+ [ (1,None,"player2"), (3,"player1","player2"), (5,None,None), (7,None,None) ],
+ [ (2,"player1",None) , (4,None,None), (6,None,None) ]
+ ]
+ wait_for( 2,
+ lambda: _generate_turn_track_snippet( dlg ) == expected
+ )
+
+ # save the scenario
+ dlg.send_keys( Keys.ESCAPE )
+ saved_scenario = save_scenario()
+ assert saved_scenario["TURN_TRACK"] == {
+ "NTURNS": "6.5",
+ "WIDTH": "4", "VERTICAL": True, "SWAP_PLAYERS": True,
+ "REINFORCEMENTS_1": "2,3", "REINFORCEMENTS_2": "1,3",
+ }
+ assert _generate_turn_track_snippet( None ) == expected
+
+ # reset the scenario
+ webdriver.refresh()
+ assert not find_child( "button.generate[data-id='turn_track']" ).is_displayed()
+
+ # load the scenario and generate the snippet
+ load_scenario( saved_scenario )
+ assert _generate_turn_track_snippet( None ) == expected
+
+ # open the turn track dialog and check that the controls were loaded correctly
+ dlg = _show_turn_track_dialog( None )
+ assert get_turn_track_nturns() == "6.5"
+ sel = Select( find_child( "select[name='width']", dlg ) )
+ assert sel.first_selected_option.get_attribute( "value" ) == "4"
+ assert find_child( "input[name='vertical']" ).is_selected()
+ assert find_child( "input[name='swap-players']" ).is_selected()
+ assert _generate_turn_track_snippet( dlg ) == expected
+
+# ---------------------------------------------------------------------
+
+def test_turn_track_droplist( webapp, webdriver ):
+ """Test updating entries in the turn track droplist (#turns)."""
+
+ # initialize
+ webapp.control_tests.set_data_dir( "{REAL}" )
+ init_webapp( webapp, webdriver, scenario_persistence=1 )
+
+ # check the initial state of the droplist
+ assert _unload_turn_track_droplist() == [
+ "", "6", "6.5", "7", "7.5", "8", "8.5", "9", "9.5", "10", "(show-dialog)"
+ ]
+
+ # configure a number of turns that is not in the default list (small)
+ sel = Select( find_child( "select[name='TURN_TRACK_NTURNS']" ) )
+ select_droplist_val( sel, "(show-dialog)" )
+ sel2 = Select( find_child( "#turn-track select[name='nturns']" ) )
+ select_droplist_val( sel2, "2" )
+ assert _unload_turn_track_droplist() == [
+ "", "2", "6", "6.5", "7", "7.5", "8", "8.5", "9", "9.5", "10"
+ ]
+
+ # configure a number of turns that is not in the default list (large)
+ select_droplist_val( sel2, "14.5" )
+ expected = [ "", "6", "6.5", "7", "7.5", "8", "8.5", "9", "9.5", "10", "14.5" ]
+ assert _unload_turn_track_droplist() == expected
+
+ # save and reload the scenario
+ find_child( ".ui-dialog.turn-track" ).send_keys( Keys.ESCAPE )
+ saved_scenario = save_scenario()
+ webdriver.refresh()
+ load_scenario( saved_scenario )
+ assert _unload_turn_track_droplist() == expected
+
+ # configure a number of turns that is in the default list
+ sel = Select( find_child( "select[name='TURN_TRACK_NTURNS']" ) )
+ select_droplist_val( sel, "8" )
+ assert _unload_turn_track_droplist() == [
+ "", "6", "6.5", "7", "7.5", "8", "8.5", "9", "9.5", "10"
+ ]
+
+ # disable the turn track
+ select_droplist_val( sel, "" )
+ assert _unload_turn_track_droplist() == [
+ "", "6", "6.5", "7", "7.5", "8", "8.5", "9", "9.5", "10", "(show-dialog)"
+ ]
+
+# ---------------------------------------------------------------------
+
+def _show_turn_track_dialog( nturns ):
+ """Show the TURN TRACK dialog."""
+ if nturns:
+ set_turn_track_nturns( nturns )
+ btn = wait_for_elem( 2, "button#turn-track-settings" )
+ btn.click()
+ dlg = wait_for_elem( 2, ".ui-dialog.turn-track" )
+ return dlg
+
+def _generate_turn_track_snippet( dlg ):
+ """Generate a turn track snippet."""
+
+ # generate the snippet
+ btn = find_child( "button.snippet", dlg ) if dlg else find_child( "button.generate[data-id='turn_track']" )
+ assert btn.is_displayed()
+ btn.click()
+ clipboard = wait_for_clipboard( 2, "