From d3a2e2b5a903a25b6fbd1e41cea76d3ecf59e7aa Mon Sep 17 00:00:00 2001 From: Taka Date: Thu, 9 Aug 2018 12:17:56 +0000 Subject: [PATCH] Tightened up the tests. --- vasl_templates/webapp/tests/test_ob.py | 156 ++++++--------- vasl_templates/webapp/tests/test_players.py | 39 ++-- .../webapp/tests/test_scenario_persistence.py | 101 ++++------ vasl_templates/webapp/tests/test_snippets.py | 182 ++++++++---------- vasl_templates/webapp/tests/test_ssr.py | 11 +- .../webapp/tests/test_template_packs.py | 127 ++++++------ .../webapp/tests/test_vehicles_ordnance.py | 11 +- .../webapp/tests/test_vo_reports.py | 2 +- vasl_templates/webapp/tests/utils.py | 121 +++++++++--- 9 files changed, 353 insertions(+), 397 deletions(-) diff --git a/vasl_templates/webapp/tests/test_ob.py b/vasl_templates/webapp/tests/test_ob.py index 2ac7c64..a2564d2 100644 --- a/vasl_templates/webapp/tests/test_ob.py +++ b/vasl_templates/webapp/tests/test_ob.py @@ -4,10 +4,10 @@ import re import types from selenium.webdriver.support.ui import Select -from selenium.webdriver.common.action_chains import ActionChains -from vasl_templates.webapp.tests.utils import get_nationalities, get_clipboard, get_stored_msg -from vasl_templates.webapp.tests.utils import select_tab, find_child, find_children, click_dialog_button +from vasl_templates.webapp.tests.utils import \ + get_nationalities, get_clipboard, get_stored_msg, select_tab, find_child, find_children, \ + add_simple_note, edit_simple_note, get_sortable_entry_count, drag_sortable_entry_to_trash # --------------------------------------------------------------------- @@ -29,51 +29,61 @@ def _do_test_ob_entries( webapp, webdriver, ob_type ): # initialize webdriver.get( webapp.url_for( "main" ) ) - colors = { - "german": "col=[OBCOL:german/OBCOL2:german]", #.format( ob_type ) , - "russian": "col=[OBCOL:russian/OBCOL2:russian]" #.format( ob_type ) - } + sortable1 = find_child( "#{}-sortable_1".format( ob_type ) ) + sortable2 = find_child( "#{}-sortable_2".format( ob_type ) ) # generate OB setup/note snippets for both players - def check_snippet( player_id, entry_no, expected ): + select_tab( "ob1" ) + add_simple_note( sortable1, "{} #1".format(ob_type), None ) + add_simple_note( sortable1, "{} #2".format(ob_type), "2px" ) + select_tab( "ob2" ) + add_simple_note( sortable2, "{} #3".format(ob_type), "3px" ) + + # check that snippets are generated correctly + def check_snippet( sortable, entry_no, expected ): """Generate the snippet for an OB setup/note.""" - select_tab( "ob{}".format( player_id ) ) - elems = find_children( "#{}-sortable_{} li input[type='button']".format( ob_type, player_id ) ) + elems = find_children( "li input[type='button']", sortable ) elems[entry_no].click() if ob_type == "ob_notes": expected = re.sub( r" \(col=.*?\)", "", expected ) assert get_clipboard() == expected - _do_add_ob_entry( webdriver, 1, ob_type, "{} #1".format(ob_type), None ) - _do_add_ob_entry( webdriver, 1, ob_type, "{} #2".format(ob_type), "2px" ) - _do_add_ob_entry( webdriver, 2, ob_type, "{} #3".format(ob_type), "3px" ) - check_snippet( 1, 0, "[German] [{} #1] ({})".format( ob_type, colors["german"] ) ) - check_snippet( 1, 1, "[German] [{} #2] ({}) (width=[2px])".format( ob_type, colors["german"] ) ) - check_snippet( 2, 0, "[Russian] [{} #3] ({}) (width=[3px])".format( ob_type, colors["russian"] ) ) + select_tab( "ob1" ) + check_snippet( sortable1, 0, + "[German] [{} #1] (col=[OBCOL:german/OBCOL2:german])".format( ob_type ) + ) + check_snippet( sortable1, 1, + "[German] [{} #2] (col=[OBCOL:german/OBCOL2:german]) (width=[2px])".format( ob_type ) + ) + select_tab( "ob2" ) + check_snippet( sortable2, 0, + "[Russian] [{} #3] (col=[OBCOL:russian/OBCOL2:russian]) (width=[3px])".format( ob_type ) + ) # make some changes and check the snippets again - _do_edit_ob_entry( webdriver, 2, ob_type, 0, "updated {} #3".format(ob_type), "" ) - _do_edit_ob_entry( webdriver, 1, ob_type, 1, "updated {} #2".format(ob_type), "200px" ) - _do_edit_ob_entry( webdriver, 1, ob_type, 0, None, "100px" ) - check_snippet( 2, 0, "[Russian] [updated {} #3] ({})".format( ob_type, colors["russian"] ) ) - check_snippet( 1, 1, "[German] [updated {} #2] ({}) (width=[200px])".format( ob_type, colors["german"] ) ) - check_snippet( 1, 0, "[German] [{} #1] ({}) (width=[100px])".format( ob_type, colors["german"] ) ) + edit_simple_note( sortable2, 0, "updated {} #3".format(ob_type), "" ) + select_tab( "ob1" ) + edit_simple_note( sortable1, 1, "updated {} #2".format(ob_type), "200px" ) + edit_simple_note( sortable1, 0, None, "100px" ) + select_tab( "ob2" ) + check_snippet( sortable2, 0, + "[Russian] [updated {} #3] (col=[OBCOL:russian/OBCOL2:russian])".format( ob_type ) + ) + select_tab( "ob1" ) + check_snippet( sortable1, 1, + "[German] [updated {} #2] (col=[OBCOL:german/OBCOL2:german]) (width=[200px])".format( ob_type ) + ) + check_snippet( sortable1, 0, + "[German] [{} #1] (col=[OBCOL:german/OBCOL2:german]) (width=[100px])".format( ob_type ) + ) # delete an OB setup/note by dragging it into the trash - def count_entries( player_id ): - """Count the number of OB setup/notes.""" - elems = find_children( "#{}-sortable_{} li".format( ob_type, player_id ) ) - return len(elems) - select_tab( "ob1" ) - assert count_entries(1) == 2 - elems = find_children( "#{}-sortable_1 li".format( ob_type ) ) - trash = find_child( "#{}-trash_1".format( ob_type ) ) - ActionChains(webdriver).drag_and_drop( elems[1], trash ).perform() - assert count_entries(1) == 1 + assert get_sortable_entry_count( sortable1 ) == 2 + drag_sortable_entry_to_trash( sortable1, 1 ) + assert get_sortable_entry_count( sortable1 ) == 1 # delete an OB setup/note by emptying its caption - _do_edit_ob_entry( webdriver, 1, ob_type, 0, "", None ) - click_dialog_button( "OK" ) # nb: confirm the deletion - assert count_entries(1) == 0 + edit_simple_note( sortable1, 0, "", None ) + assert get_sortable_entry_count( sortable1 ) == 0 # --------------------------------------------------------------------- @@ -85,22 +95,22 @@ def test_nationality_specific( webapp, webdriver ): nationalities = get_nationalities( webapp ) # initialize + scenario_date = find_child( "#panel-scenario input[name='SCENARIO_DATE']" ) def set_scenario_date( date ): """Set the scenario date.""" select_tab( "scenario" ) - elem = find_child( "#panel-scenario input[name='SCENARIO_DATE']" ) - elem.clear() - elem.send_keys( "{:02}/01/{:04}".format( date[1], date[0] ) ) + scenario_date.clear() + scenario_date.send_keys( "{:02}/01/{:04}".format( date[1], date[0] ) ) # initialize def check_pf_snippets(): """Check that the PF snippets are generated correctly.""" + pf_btn = find_child( "input[type='button'][data-id='pf']" ) def do_test( date, expected, warning ): #pylint: disable=missing-docstring # test snippet generation set_scenario_date( date ) select_tab( "ob1" ) - elem = find_child( "input[type='button'][data-id='pf']" ) - elem.click() + pf_btn.click() assert get_clipboard() == expected # check if a warning was issued last_warning = get_stored_msg( "_last-warning_" ) or "" @@ -120,12 +130,12 @@ def test_nationality_specific( webapp, webdriver ): # initialize def check_baz_snippets(): """Check that the BAZ snippets are generated correctly.""" + baz_btn = find_child( "input[type='button'][data-id='baz']" ) def do_test( date, expected ): #pylint: disable=missing-docstring # test snippet generation set_scenario_date( date ) select_tab( "ob1" ) - elem = find_child( "input[type='button'][data-id='baz']" ) - elem.click() + baz_btn.click() assert get_clipboard() == expected # check if a warning was issued last_warning = get_stored_msg( "_last-warning_" ) or "" @@ -155,21 +165,23 @@ def test_nationality_specific( webapp, webdriver ): "baz": [ "american", check_baz_snippets ], "piat": [ "british", "piat template ; col=[OBCOL:british]/[OBCOL2:british]" ], } + btn_elems = { + btn: find_child( "input[type='button'][data-id='{}']".format( btn ) ) + for btn in nationality_specific_buttons + } # iterate through each nationality + player1_sel = Select( find_child( "select[name='PLAYER_1']" ) ) for nat in nationalities: # change the nationality for player 1 select_tab( "scenario" ) - sel = Select( - find_child( "select[name='PLAYER_1']" ) - ) - sel.select_by_value( nat ) - select_tab( "ob1" ) + player1_sel.select_by_value( nat ) # check the nationality-specific buttons + select_tab( "ob1" ) for button_id,expected in nationality_specific_buttons.items(): - elem = find_child( "input[type='button'][data-id='{}']".format( button_id ) ) + elem = btn_elems[ button_id ] if nat == expected[0]: # the button should be shown for this nationality assert elem.is_displayed() @@ -184,51 +196,3 @@ def test_nationality_specific( webapp, webdriver ): else: # it should be hidden for all other nationalities assert not elem.is_displayed() - -# --------------------------------------------------------------------- - -def add_ob_setup( webdriver, player_id, caption, width ): - """Add a new OB setup.""" - _do_add_ob_entry( webdriver, player_id, "ob_setups", caption, width ) - -def add_ob_note( webdriver, player_id, caption, width ): - """Add a new OB note.""" - _do_add_ob_entry( webdriver, player_id, "ob_notes", caption, width ) - -# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -def _do_add_ob_entry( webdriver, player_id, ob_type, caption, width ): - """Add a new OB setup/note.""" - select_tab( "ob{}".format( player_id ) ) - elem = find_child( "#{}-add_{}".format( ob_type, player_id ) ) - elem.click() - _do_edit_ob_entry( webdriver, player_id, ob_type, None, caption, width ) - -# --------------------------------------------------------------------- - -def edit_ob_setup( webdriver, player_id, entry_no, caption, width ): - """Edit an OB setup.""" - _do_edit_ob_entry( webdriver, player_id, "ob_setups", entry_no, caption, width ) - -# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -def _do_edit_ob_entry( webdriver, player_id, ob_type, entry_no, caption, width ): - """Edit an OB setup/note.""" - - # locate the requested entry and start editing it - if entry_no is not None: - select_tab( "ob{}".format( player_id ) ) - elems = find_children( "#{}-sortable_{} li".format( ob_type, player_id ) ) - elem = elems[ entry_no ] - ActionChains(webdriver).double_click( elem ).perform() - - # edit the OB setup/note - if caption is not None: - elem = find_child( "#edit-simple_note textarea" ) - elem.clear() - elem.send_keys( caption ) - if width is not None: - elem = find_child( "#edit-simple_note input[type='text']" ) - elem.clear() - elem.send_keys( width ) - click_dialog_button( "OK" ) diff --git a/vasl_templates/webapp/tests/test_players.py b/vasl_templates/webapp/tests/test_players.py index fa7c6ae..1254e8e 100644 --- a/vasl_templates/webapp/tests/test_players.py +++ b/vasl_templates/webapp/tests/test_players.py @@ -6,15 +6,6 @@ from vasl_templates.webapp.tests.utils import get_nationalities, select_tab, fin # --------------------------------------------------------------------- -def _get_player( webdriver, player_id ): #pylint: disable=unused-argument - """Get the nationality of the specified player.""" - sel = Select( - find_child( "select[name='PLAYER_{}']".format( player_id ) ) - ) - return sel.first_selected_option.get_attribute( "value" ) - -# --------------------------------------------------------------------- - def test_player_change( webapp, webdriver ): """Test changing players.""" @@ -22,25 +13,25 @@ def test_player_change( webapp, webdriver ): webdriver.get( webapp.url_for( "main" ) ) select_tab( "scenario" ) nationalities = get_nationalities( webapp ) + player_sel = { + 1: Select( find_child( "select[name='PLAYER_1']" ) ), + 2: Select( find_child( "select[name='PLAYER_2']" ) ) + } + ob_tabs = { + 1: find_child( "#tabs .ui-tabs-nav a[href='#tabs-ob1']" ), + 2: find_child( "#tabs .ui-tabs-nav a[href='#tabs-ob2']" ) + } # make sure that the UI was updated correctly for the initial players for player_no in [1,2]: - player_id = _get_player( webdriver, player_no ) - elem = find_child( "#tabs .ui-tabs-nav a[href='#tabs-ob{}']".format( player_no ) ) - assert elem.text.strip() == "{} OB".format( nationalities[player_id]["display_name"] ) + player_id = player_sel[player_no].first_selected_option.get_attribute( "value" ) + expected = "{} OB".format( nationalities[player_id]["display_name"] ) + assert ob_tabs[player_no].text.strip() == expected # change player 1 - sel = Select( - find_child( "select[name='PLAYER_1']" ) - ) - sel.select_by_value( "finnish" ) - elem = find_child( "#tabs .ui-tabs-nav a[href='#tabs-ob1']" ) - assert elem.text.strip() == "{} OB".format( nationalities["finnish"]["display_name"] ) + player_sel[1].select_by_value( "finnish" ) + assert ob_tabs[1].text.strip() == "{} OB".format( nationalities["finnish"]["display_name"] ) # change player 2 - sel = Select( - find_child( "select[name='PLAYER_2']" ) - ) - sel.select_by_value( "japanese" ) - elem = find_child( "#tabs .ui-tabs-nav a[href='#tabs-ob2']" ) - assert elem.text.strip() == "{} OB".format( nationalities["japanese"]["display_name"] ) + player_sel[2].select_by_value( "japanese" ) + assert ob_tabs[2].text.strip() == "{} OB".format( nationalities["japanese"]["display_name"] ) diff --git a/vasl_templates/webapp/tests/test_scenario_persistence.py b/vasl_templates/webapp/tests/test_scenario_persistence.py index 5cd878d..6b4af89 100644 --- a/vasl_templates/webapp/tests/test_scenario_persistence.py +++ b/vasl_templates/webapp/tests/test_scenario_persistence.py @@ -4,24 +4,18 @@ import json from selenium.webdriver.support.ui import Select -from vasl_templates.webapp.tests.utils import set_template_params, select_tab, select_menu_option -from vasl_templates.webapp.tests.utils import get_stored_msg, set_stored_msg, find_child, find_children +from vasl_templates.webapp.tests.utils import \ + set_template_params, select_tab, select_menu_option, get_sortable_entry_text, \ + get_stored_msg, set_stored_msg, find_child, find_children # --------------------------------------------------------------------- -def test_scenario_persistence( webapp, webdriver ): +def test_scenario_persistence( webapp, webdriver ): #pylint: disable=too-many-locals """Test loading/saving scenarios.""" # initialize webdriver.get( webapp.url_for( "main", scenario_persistence=1 ) ) - # initialize - def load_scenario_fields( fields ): - """Load the scenario fields.""" - for tab_id in fields: - select_tab( tab_id ) - set_template_params( fields[tab_id] ) - # load the scenario fields scenario_params = { "scenario": { @@ -57,7 +51,9 @@ def test_scenario_persistence( webapp, webdriver ): "ORDNANCE_WIDTH_2": "303", }, } - load_scenario_fields( scenario_params ) + for tab_id,fields in scenario_params.items(): + select_tab( tab_id ) + set_template_params( fields ) # save the scenario and check the results saved_scenario = _save_scenario() @@ -66,10 +62,8 @@ def test_scenario_persistence( webapp, webdriver ): } assert saved_scenario == expected - # reset the scenario + # reset the scenario and check the save results select_menu_option( "new_scenario" ) - - # check the save results data = _save_scenario() data2 = { k: v for k,v in data.items() if v } assert data2 == { @@ -77,27 +71,29 @@ def test_scenario_persistence( webapp, webdriver ): "PLAYER_2": "russian", "PLAYER_2_ELR": "5", "PLAYER_2_SAN": "2", } - # load a scenario - _load_scenario( saved_scenario ) + # initialize + ssrs = find_child( "#ssr-sortable" ) + ob_setups1, ob_notes1 = find_child("#ob_setups-sortable_1"), find_child("#ob_notes-sortable_1") + ob_setups2, ob_notes2 = find_child("#ob_setups-sortable_2"), find_child("#ob_notes-sortable_2") + vehicles1, ordnance1 = find_child("#vehicle-sortable_1"), find_child("#ordnance-sortable_1") + vehicles2, ordnance2 = find_child("#vehicle-sortable_2"), find_child("#ordnance-sortable_2") + elems = { + c.get_attribute("name"): c + for elem_type in ("input","textarea","select") for c in find_children(elem_type) + } - # make sure the scenario was loaded into the UI correctly + # load a scenario and make sure it was loaded into the UI correctly + _load_scenario( saved_scenario ) for tab_id in scenario_params: select_tab( tab_id ) for field,val in scenario_params[tab_id].items(): - if field == "SCENARIO_NOTES": - continue # nb: this requires special handling, we do it below - if field == "SSR": - continue # nb: this requires special handling, we do it below - if field in ("OB_SETUPS_1","OB_SETUPS_2"): - continue # nb: this requires special handling, we do it below - if field in ("OB_NOTES_1","OB_NOTES_2"): - continue # nb: this requires special handling, we do it below + if field in ("SCENARIO_NOTES","SSR"): + continue # nb: these require special handling, we do it below + if field in ("OB_SETUPS_1","OB_SETUPS_2","OB_NOTES_1","OB_NOTES_2"): + continue # nb: these require special handling, we do it below if field in ("VEHICLES_1","ORDNANCE_1","VEHICLES_2","ORDNANCE_2"): - continue # nb: this requires special handling, we do it below - elem = next( c for c in ( \ - find_child( "{}[name='{}']".format(elem_type,field) ) \ - for elem_type in ["input","textarea","select"] - ) if c ) + continue # nb: these require special handling, we do it below + elem = elems[ field ] if elem.tag_name == "select": assert Select(elem).first_selected_option.get_attribute("value") == val else: @@ -105,16 +101,17 @@ def test_scenario_persistence( webapp, webdriver ): select_tab( "scenario" ) scenario_notes = [ c.text for c in find_children("#scenario_notes-sortable li") ] assert scenario_notes == [ sn["caption"] for sn in scenario_params["scenario"]["SCENARIO_NOTES"] ] - ssrs = _get_ssrs() - assert ssrs == scenario_params["scenario"]["SSR"] - assert _get_ob_entries("ob_setups",1) == [ obs["caption"] for obs in scenario_params["ob1"]["OB_SETUPS_1"] ] - assert _get_ob_entries("ob_setups",2) == [ obs["caption"] for obs in scenario_params["ob2"]["OB_SETUPS_2"] ] - assert _get_ob_entries("ob_notes",1) == [ obs["caption"] for obs in scenario_params["ob1"]["OB_NOTES_1"] ] - assert _get_ob_entries("ob_notes",2) == [ obs["caption"] for obs in scenario_params["ob2"]["OB_NOTES_2"] ] - assert _get_vo("vehicle",1) == scenario_params["ob1"]["VEHICLES_1"] - assert _get_vo("ordnance",1) == scenario_params["ob1"]["ORDNANCE_1"] - assert _get_vo("vehicle",2) == scenario_params["ob2"]["VEHICLES_2"] - assert _get_vo("ordnance",2) == scenario_params["ob2"]["ORDNANCE_2"] + assert get_sortable_entry_text(ssrs) == scenario_params["scenario"]["SSR"] + select_tab( "ob1" ) + assert get_sortable_entry_text(ob_setups1) == [ obs["caption"] for obs in scenario_params["ob1"]["OB_SETUPS_1"] ] + assert get_sortable_entry_text(ob_notes1) == [ obs["caption"] for obs in scenario_params["ob1"]["OB_NOTES_1"] ] + assert get_sortable_entry_text(vehicles1) == scenario_params["ob1"]["VEHICLES_1"] + assert get_sortable_entry_text(ordnance1) == scenario_params["ob1"]["ORDNANCE_1"] + select_tab( "ob2" ) + assert get_sortable_entry_text(ob_setups2) == [ obs["caption"] for obs in scenario_params["ob2"]["OB_SETUPS_2"] ] + assert get_sortable_entry_text(ob_notes2) == [ obs["caption"] for obs in scenario_params["ob2"]["OB_NOTES_2"] ] + assert get_sortable_entry_text(vehicles2) == scenario_params["ob2"]["VEHICLES_2"] + assert get_sortable_entry_text(ordnance2) == scenario_params["ob2"]["ORDNANCE_2"] # --------------------------------------------------------------------- @@ -126,9 +123,10 @@ def test_loading_ssrs( webapp, webdriver ): _ = _save_scenario() # nb: force the "scenario-persistence" element to be created # initialize + sortable = find_child( "#ssr-sortable" ) def do_test( ssrs ): # pylint: disable=missing-docstring _load_scenario( { "SSR": ssrs } ) - assert _get_ssrs() == ssrs + assert get_sortable_entry_text(sortable) == ssrs # load a scenario that has SSR's into a UI with no SSR's do_test( [ "ssr 1", "ssr 2" ] ) @@ -176,24 +174,3 @@ def _save_scenario(): select_menu_option( "save_scenario" ) data = get_stored_msg( "scenario_persistence" ) return json.loads( data ) - -def _get_ssrs(): - """Get the SSR's from the UI.""" - select_tab( "scenario" ) - return [ c.text for c in find_children("#ssr-sortable li") ] - -def _get_ob_entries( ob_type, player_id ): - """Get the OB setup/notes from the UI.""" - select_tab( "ob{}".format( player_id ) ) - return [ - c.text - for c in find_children( "#{}-sortable_{} li".format( ob_type, player_id ) ) - ] - -def _get_vo( vo_type, player_id ): - """Get the vehicles/ordnance from the UI.""" - select_tab( "ob{}".format( player_id ) ) - return [ - c.text - for c in find_children( "#{}-sortable_{} li".format( vo_type, player_id ) ) - ] diff --git a/vasl_templates/webapp/tests/test_snippets.py b/vasl_templates/webapp/tests/test_snippets.py index 1395716..6259d05 100644 --- a/vasl_templates/webapp/tests/test_snippets.py +++ b/vasl_templates/webapp/tests/test_snippets.py @@ -1,12 +1,12 @@ """ Test HTML snippet generation. """ from selenium.webdriver.common.keys import Keys -from selenium.webdriver.common.action_chains import ActionChains -from vasl_templates.webapp.tests.test_ob import add_ob_setup, add_ob_note from vasl_templates.webapp.tests.utils import select_tab, set_template_params, get_clipboard -from vasl_templates.webapp.tests.utils import get_stored_msg, dismiss_notifications, find_child, find_children -from vasl_templates.webapp.tests.utils import for_each_template, wait_for, click_dialog_button +from vasl_templates.webapp.tests.utils import \ + get_stored_msg, dismiss_notifications, find_child, \ + for_each_template, wait_for, add_simple_note, edit_simple_note, \ + get_sortable_entry_count, generate_sortable_entry_snippet, drag_sortable_entry_to_trash # --------------------------------------------------------------------- @@ -16,9 +16,10 @@ def test_scenario_snippets( webapp, webdriver ): # initialize webdriver.get( webapp.url_for( "main", store_msgs=1 ) ) select_tab( "scenario" ) + btn = find_child( "input.generate[data-id='scenario']" ) # generate a SCENARIO snippet - _test_snippet( webdriver, "scenario", { + _test_snippet( btn, { "SCENARIO_NAME": "my cool scenario", "SCENARIO_LOCATION": "right here", "SCENARIO_DATE": "01/02/1942", @@ -28,7 +29,7 @@ def test_scenario_snippets( webapp, webdriver ): ) # generate a SCENARIO snippet with some fields missing - _test_snippet( webdriver, "scenario", { + _test_snippet( btn, { "SCENARIO_NAME": "my scenario", "SCENARIO_LOCATION": None, "SCENARIO_DATE": None, @@ -38,7 +39,7 @@ def test_scenario_snippets( webapp, webdriver ): ) # generate a SCENARIO snippet with all fields missing - _test_snippet( webdriver, "scenario", { + _test_snippet( btn, { "SCENARIO_NAME": None, "SCENARIO_LOCATION": None, "SCENARIO_DATE": None, @@ -48,7 +49,7 @@ def test_scenario_snippets( webapp, webdriver ): ) # generate a SCENARIO snippet with a snippet width - _test_snippet( webdriver, "scenario", { + _test_snippet( btn, { "SCENARIO_NAME": "test", "SCENARIO_LOCATION": "here", "SCENARIO_DATE": "01/02/1942", @@ -58,7 +59,7 @@ def test_scenario_snippets( webapp, webdriver ): None ) -# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +# --------------------------------------------------------------------- def test_vc_snippets( webapp, webdriver ): """Test HTML snippet generation.""" @@ -66,9 +67,10 @@ def test_vc_snippets( webapp, webdriver ): # initialize webdriver.get( webapp.url_for( "main", store_msgs=1 ) ) select_tab( "scenario" ) + btn = find_child( "input.generate[data-id='victory_conditions']" ) # generate a VC snippet - _test_snippet( webdriver, "victory_conditions", { + _test_snippet( btn, { "VICTORY_CONDITIONS": "Kill 'Em All!", }, "VC: [Kill 'Em All!]", @@ -76,7 +78,7 @@ def test_vc_snippets( webapp, webdriver ): ) # generate an empty VC snippet - _test_snippet( webdriver, "victory_conditions", { + _test_snippet( btn, { "VICTORY_CONDITIONS": "", }, "VC: []", @@ -84,7 +86,7 @@ def test_vc_snippets( webapp, webdriver ): ) # generate a VC snippet with a width - _test_snippet( webdriver, "victory_conditions", { + _test_snippet( btn, { "VICTORY_CONDITIONS": "Kill 'Em All!", "VICTORY_CONDITIONS_WIDTH": "100px", }, @@ -92,7 +94,7 @@ def test_vc_snippets( webapp, webdriver ): None ) -# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +# --------------------------------------------------------------------- def test_scenario_notes_snippets( webapp, webdriver ): """Test HTML snippet generation.""" @@ -102,59 +104,22 @@ def test_scenario_notes_snippets( webapp, webdriver ): select_tab( "scenario" ) # add some scenario notes and check their snippets - def check_snippet( entry_no, expected ): - """Check the snippet for a scenario note.""" - elems = find_children( "#scenario_notes-sortable li input[type='button']" ) - elems[entry_no].click() - assert get_clipboard() == expected - _add_scenario_note( webdriver, "scenario note #1", None ) - _add_scenario_note( webdriver, "scenario note #2", "100px" ) - check_snippet( 0, "[scenario note #1]" ) - check_snippet( 1, "[scenario note #2] (width=[100px])" ) + sortable = find_child( "#scenario_notes-sortable" ) + add_simple_note( sortable, "scenario note #1", None ) + add_simple_note( sortable, "scenario note #2", "100px" ) + assert generate_sortable_entry_snippet( sortable, 0 ) == "[scenario note #1]" + assert generate_sortable_entry_snippet( sortable, 1 ) == "[scenario note #2] (width=[100px])" # delete a scenario note by dragging it into the trash - def count_entries(): - """Count the number of scenario notes.""" - elems = find_children( "#scenario_notes-sortable li" ) - return len(elems) - assert count_entries() == 2 - elems = find_children( "#scenario_notes-sortable li" ) - trash = find_child( "#scenario_notes-trash" ) - ActionChains(webdriver).drag_and_drop( elems[0], trash ).perform() - assert count_entries() == 1 + assert get_sortable_entry_count( sortable ) == 2 + drag_sortable_entry_to_trash( sortable, 0 ) + assert get_sortable_entry_count( sortable ) == 1 # delete scenario note by emptying its caption - _edit_scenario_note( webdriver, 0, "", None ) - click_dialog_button( "OK" ) # nb: confirm the deletion - assert count_entries() == 0 - -def _add_scenario_note( webdriver, caption, width ): #FIXME! move to utils - """Add a new scenario note.""" - elem = find_child( "#scenario_notes-add" ) - elem.click() - _edit_scenario_note( webdriver, None, caption, width ) - -def _edit_scenario_note( webdriver, entry_no, caption, width ): #FIXME! move to utils - """Edit a scenario note.""" - - # locate the requested entry and start editing it - if entry_no is not None: - elems = find_children( "#scenario_notes-sortable li" ) - elem = elems[ entry_no ] - ActionChains(webdriver).double_click( elem ).perform() - - # edit the scenario note - if caption is not None: - elem = find_child( "#edit-simple_note textarea" ) - elem.clear() - elem.send_keys( caption ) - if width is not None: - elem = find_child( "#edit-simple_note input[type='text']" ) - elem.clear() - elem.send_keys( width ) - click_dialog_button( "OK" ) + edit_simple_note( sortable, 0, "", None ) + assert get_sortable_entry_count( sortable ) == 0 -# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +# --------------------------------------------------------------------- def test_players_snippets( webapp, webdriver ): """Test HTML snippet generation.""" @@ -162,9 +127,10 @@ def test_players_snippets( webapp, webdriver ): # initialize webdriver.get( webapp.url_for( "main", store_msgs=1 ) ) select_tab( "scenario" ) + btn = find_child( "input.generate[data-id='players']" ) # generate a PLAYERS snippet - _test_snippet( webdriver, "players", { + _test_snippet( btn, { "PLAYER_1": "french", "PLAYER_1_ELR": "1", "PLAYER_1_SAN": "2", @@ -177,47 +143,13 @@ def test_players_snippets( webapp, webdriver ): ) # generate a PLAYERS snippet with both players the same nationality - _test_snippet( webdriver, "players", { + _test_snippet( btn, { "PLAYER_1": "british", }, "player1=[british:British] ; ELR=[1] ; SAN=[2] | player2=[british:British] ; ELR=[3] ; SAN=[4]", [ "Both players have the same nationality!" ], ) -# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -def _test_snippet( webdriver, template_id, params, expected, expected2 ): #pylint: disable=unused-argument - """Do a single test.""" - - # set the template parameters - set_template_params( params ) - - # generate the snippet - submit = find_child( "input.generate[data-id='{}']".format(template_id) ) - submit.click() - snippet = get_clipboard() - lines = [ l.strip() for l in snippet.split("\n") ] - snippet = " | ".join( l for l in lines if l ) - assert snippet == expected - - # check warnings for mandatory parameters - last_warning = get_stored_msg( "_last-warning_" ) or "" - if isinstance( expected2, list): - # check for mandatory parameters - param_names = [ "scenario name", "scenario location", "scenario date" ] - for pname in param_names: - if pname in expected2: - assert pname in last_warning - else: - assert pname not in last_warning - elif isinstance(expected2, str): - # check for a specific error message - assert expected2 == last_warning - else: - # make sure there was no warning message - assert expected2 is None - assert not last_warning - # --------------------------------------------------------------------- def test_edit_templates( webapp, webdriver ): @@ -225,6 +157,14 @@ def test_edit_templates( webapp, webdriver ): # initialize webdriver.get( webapp.url_for( "main", edit_template_links=1 ) ) + ob_setups = { + 1: find_child( "#ob_setups-sortable_1" ), + 2: find_child( "#ob_setups-sortable_2" ) + } + ob_notes = { + 1: find_child( "#ob_notes-sortable_1" ), + 2: find_child( "#ob_notes-sortable_2" ) + } # try uploading a customized version of each template def edit_template( template_id ): @@ -257,8 +197,9 @@ def test_edit_templates( webapp, webdriver ): edit_template( "scenario_note" ) # check that the new template is being used - _add_scenario_note( webdriver, "scenario note (ignored)", None ) - elem = find_child( "#scenario_notes-sortable li input[type='button']" ) + sortable = find_child( "#scenario_notes-sortable" ) + add_simple_note( sortable, "scenario note (ignored)", None ) + elem = find_child( "li input[type='button']", sortable ) elem.click() assert get_clipboard() == "EDITED TEMPLATE: scenario_note" @@ -270,8 +211,10 @@ def test_edit_templates( webapp, webdriver ): # check that the new template is being used for player_id in range(1,2+1): - add_ob_setup( webdriver, player_id, "ob setup (ignored)", None ) - elem = find_child( "#ob_setups-sortable_{} li input[type='button']".format( player_id ) ) + select_tab( "ob{}".format( player_id ) ) + sortable = ob_setups[ player_id ] + add_simple_note( sortable, "ob setup (ignored)", None ) + elem = find_child( "li input[type='button']", sortable ) elem.click() assert get_clipboard() == "EDITED TEMPLATE: ob_setup" @@ -283,7 +226,40 @@ def test_edit_templates( webapp, webdriver ): # check that the new template is being used for player_id in range(1,2+1): - add_ob_note( webdriver, player_id, "ob note (ignored)", None ) - elem = find_child( "#ob_notes-sortable_{} li input[type='button']".format( player_id ) ) + select_tab( "ob{}".format( player_id ) ) + sortable = ob_notes[ player_id ] + add_simple_note( sortable, "ob note (ignored)", None ) + elem = find_child( "li input[type='button']", sortable ) elem.click() assert get_clipboard() == "EDITED TEMPLATE: ob_note" + +# --------------------------------------------------------------------- + +def _test_snippet( btn, params, expected, expected2 ): + """Do a single test.""" + + # set the template parameters and generate the snippet + set_template_params( params ) + btn.click() + snippet = get_clipboard() + lines = [ l.strip() for l in snippet.split("\n") ] + snippet = " | ".join( l for l in lines if l ) + assert snippet == expected + + # check warnings for mandatory parameters + last_warning = get_stored_msg( "_last-warning_" ) or "" + if isinstance( expected2, list): + # check for mandatory parameters + param_names = [ "scenario name", "scenario location", "scenario date" ] + for pname in param_names: + if pname in expected2: + assert pname in last_warning + else: + assert pname not in last_warning + elif isinstance(expected2, str): + # check for a specific error message + assert expected2 == last_warning + else: + # make sure there was no warning message + assert expected2 is None + assert not last_warning diff --git a/vasl_templates/webapp/tests/test_ssr.py b/vasl_templates/webapp/tests/test_ssr.py index 1118d24..c0b1211 100644 --- a/vasl_templates/webapp/tests/test_ssr.py +++ b/vasl_templates/webapp/tests/test_ssr.py @@ -4,8 +4,8 @@ import html from selenium.webdriver.common.action_chains import ActionChains -from vasl_templates.webapp.tests.utils import select_tab, find_child, find_children -from vasl_templates.webapp.tests.utils import get_clipboard, dismiss_notifications, click_dialog_button +from vasl_templates.webapp.tests.utils import \ + select_tab, find_child, find_children, get_clipboard, dismiss_notifications, click_dialog_button # --------------------------------------------------------------------- @@ -18,6 +18,7 @@ def test_ssr( webapp, webdriver ): # initialize expected = [] + generate_snippet_btn = find_child( "input[type='button'][data-id='ssr']" ) def _add_ssr( val ): expected.append( val ) add_ssr( webdriver, val ) @@ -28,8 +29,7 @@ def test_ssr( webapp, webdriver ): check_snippet() def check_snippet( width=None ): """Check the generated SSR snippet.""" - btn = find_child( "input[type='button'][data-id='ssr']" ) - btn.click() + generate_snippet_btn.click() val = "\n".join( "(*) [{}]".format(e) for e in expected ) if width: val += "\nwidth = [{}]".format( width ) @@ -77,7 +77,8 @@ def edit_ssr( webdriver, ssr_no, val ): # locate the requested SSR and start editing it if ssr_no is not None: - elems = find_children( "#ssr-sortable li" ) + sortable = find_child( "#ssr-sortable" ) + elems = find_children( "li", sortable ) elem = elems[ ssr_no ] ActionChains(webdriver).double_click( elem ).perform() diff --git a/vasl_templates/webapp/tests/test_template_packs.py b/vasl_templates/webapp/tests/test_template_packs.py index f5e170d..8e4a4b2 100644 --- a/vasl_templates/webapp/tests/test_template_packs.py +++ b/vasl_templates/webapp/tests/test_template_packs.py @@ -8,10 +8,9 @@ import base64 from selenium.webdriver.support.ui import Select from vasl_templates.webapp import snippets -from vasl_templates.webapp.tests import test_ob -from vasl_templates.webapp.tests.utils import select_tab, select_menu_option, dismiss_notifications -from vasl_templates.webapp.tests.utils import get_clipboard, get_stored_msg, set_stored_msg -from vasl_templates.webapp.tests.utils import for_each_template, find_child, find_children +from vasl_templates.webapp.tests.utils import \ + select_tab, select_menu_option, dismiss_notifications, get_clipboard, \ + get_stored_msg, set_stored_msg, add_simple_note, for_each_template, find_child, find_children # --------------------------------------------------------------------- @@ -26,22 +25,8 @@ def test_individual_files( webapp, webdriver ): """Test uploading a customized version of the template.""" # make sure generating a snippet returns something dismiss_notifications() - if template_id == "scenario_note": - from vasl_templates.webapp.tests.test_snippets import _add_scenario_note - select_tab( "scenario" ) - _add_scenario_note( webdriver, "test scenario note", None ) - elems = find_children( "#scenario_notes-sortable li input[type='button']" ) - elem = elems[0] - elif template_id in ("ob_setup","ob_note"): - select_tab( "ob1" ) - func = getattr( test_ob, "add_"+template_id ) - func( webdriver, 1, "test {}".format(template_id), None ) - elems = find_children( "#{}s-sortable_1 li input[type='button']".format( template_id ) ) - elem = elems[0] - else: - elem = find_child( "input.generate[data-id='{}']".format( orig_template_id ) ) - elem.click() - assert get_clipboard() != "" + elem, clipboard = _generate_snippet( template_id, orig_template_id ) + assert clipboard != "" # upload a new template fname = template_id + ".j2" set_stored_msg( "template_pack_persistence", @@ -84,9 +69,7 @@ def test_zip_files( webapp, webdriver ): assert get_stored_msg("_last-error_") is None # check that the uploaded templates are being used - _check_snippets( webdriver, - lambda tid: "Customized {}.".format( tid.upper() ) - ) + _check_snippets( lambda tid: "Customized {}.".format( tid.upper() ) ) # upload only part of template pack _upload_template_pack( zip_data[ : int(len(zip_data)/2) ] ) @@ -100,7 +83,7 @@ def test_zip_files( webapp, webdriver ): # "open file" dialog has finished, but before we read the file data (i.e. we don't execute # that bit of code since we're using the "template_pack_persistence" hack). -# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +# --------------------------------------------------------------------- def test_new_default_template_pack( webapp, webdriver, monkeypatch ): """Test changing the default template pack.""" @@ -113,11 +96,9 @@ def test_new_default_template_pack( webapp, webdriver, monkeypatch ): webdriver.get( webapp.url_for( "main" ) ) # check that the new templates are being used - _check_snippets( webdriver, - lambda tid: "New default {}.".format( tid.upper() ) - ) + _check_snippets( lambda tid: "New default {}.".format( tid.upper() ) ) -# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +# --------------------------------------------------------------------- def test_nationality_data( webapp, webdriver ): """Test a template pack with nationality data.""" @@ -127,15 +108,12 @@ def test_nationality_data( webapp, webdriver ): select_tab( "scenario" ) # select the British as player 1 - sel = Select( - find_child( "select[name='PLAYER_1']" ) - ) - sel.select_by_value( "british" ) - elem = find_child( "a[href='#tabs-ob1']" ) - assert elem.text.strip() == "British OB" - sel = Select( find_child( "select[name='PLAYER_1']" ) ) - assert sel.first_selected_option.text == "British" - players = [ o.text for o in sel.options ] + player1_sel = Select( find_child( "select[name='PLAYER_1']" ) ) + player1_sel.select_by_value( "british" ) + tab_ob1 = find_child( "a[href='#tabs-ob1']" ) + assert tab_ob1.text.strip() == "British OB" + assert player1_sel.first_selected_option.text == "British" + players = [ o.text for o in player1_sel.options ] # upload a template pack that contains nationality data zip_data = _make_zip_from_files( "with-nationality-data" ) @@ -143,45 +121,16 @@ def test_nationality_data( webapp, webdriver ): assert get_stored_msg("_last-error_") is None # check that the UI was updated correctly - elem = find_child( "a[href='#tabs-ob1']" ) - assert elem.text.strip() == "Poms! OB" - elem = find_child( "select[name='PLAYER_1']" ) - assert Select(elem).first_selected_option.text == "Poms!" + assert tab_ob1.text.strip() == "Poms! OB" + assert player1_sel.first_selected_option.text == "Poms!" # check that there is a new Korean player - players2 = [ o.text for o in sel.options ] + players2 = [ o.text for o in player1_sel.options ] players2.remove( "Korean" ) players2 = [ "British" if o == "Poms!" else o for o in players2 ] assert players2 == players -# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -def _check_snippets( webdriver, expected ): - """Check that snippets are being generated as expected.""" - - def test_template( template_id, orig_template_id ): - """Test each template.""" - dismiss_notifications() - # FIXME! this code is duplicated above - if template_id == "scenario_note": - from vasl_templates.webapp.tests.test_snippets import _add_scenario_note - select_tab( "scenario" ) - _add_scenario_note( webdriver, "test scenario note", None ) - elems = find_children( "#scenario_notes-sortable li input[type='button']" ) - elem = elems[0] - elif template_id in ("ob_setup","ob_note"): - select_tab( "ob1" ) - func = getattr( test_ob, "add_"+template_id ) - func( webdriver, 1, "test {}".format(template_id), None ) - elems = find_children( "#{}s-sortable_1 li input[type='button']".format( template_id ) ) - elem = elems[0] - else: - elem = find_child( "input.generate[data-id='{}']".format( orig_template_id ) ) - elem.click() - assert get_clipboard() == expected( template_id ) - for_each_template( test_template ) - -# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +# --------------------------------------------------------------------- def _make_zip( files ): """Generate a ZIP file.""" @@ -205,6 +154,44 @@ def _make_zip_from_files( dname ): files[fname2] = fp.read() return _make_zip( files ) +# --------------------------------------------------------------------- + +def _check_snippets( expected ): + """Check that snippets are being generated as expected.""" + + def test_template( template_id, orig_template_id ): + """Test each template.""" + dismiss_notifications() + _, clipboard = _generate_snippet( template_id, orig_template_id ) + assert clipboard == expected( template_id ) + for_each_template( test_template ) + +# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + +def _generate_snippet( template_id, orig_template_id ): + """Generate a snippet for the specified template.""" + + if template_id == "scenario_note": + # create a scenario note and generate a snippet for it + sortable = find_child( "#scenario_notes-sortable" ) + add_simple_note( sortable, "test scenario note", None ) + elems = find_children( "li input[type='button']", sortable ) + elem = elems[0] + elif template_id in ("ob_setup","ob_note"): + # create a OB setup/note and generate a snippet for it + select_tab( "ob1" ) + sortable = find_child( "#{}s-sortable_1".format( template_id ) ) + add_simple_note( sortable, "test {}".format(template_id), None ) + elems = find_children( "#{}s-sortable_1 li input[type='button']".format( template_id ) ) + elem = elems[0] + else: + # generate a snippet for the specified template + elem = find_child( "input.generate[data-id='{}']".format( orig_template_id ) ) + elem.click() + return elem, get_clipboard() + +# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + def _upload_template_pack( zip_data ): """Upload a template pack.""" set_stored_msg( "template_pack_persistence", diff --git a/vasl_templates/webapp/tests/test_vehicles_ordnance.py b/vasl_templates/webapp/tests/test_vehicles_ordnance.py index b72cb3f..8a0bee5 100644 --- a/vasl_templates/webapp/tests/test_vehicles_ordnance.py +++ b/vasl_templates/webapp/tests/test_vehicles_ordnance.py @@ -5,8 +5,9 @@ import re from selenium.webdriver.support.ui import Select from selenium.webdriver.common.action_chains import ActionChains -from vasl_templates.webapp.tests.utils import select_tab, set_template_params, find_child, find_children -from vasl_templates.webapp.tests.utils import get_clipboard, click_dialog_button, dismiss_notifications +from vasl_templates.webapp.tests.utils import \ + select_tab, set_template_params, find_child, find_children, \ + get_clipboard, click_dialog_button, dismiss_notifications # --------------------------------------------------------------------- @@ -189,18 +190,18 @@ def test_variable_capabilities( webapp, webdriver ): # add a vehicle add_vo( "vehicle", 2, "Churchill III(b)" ) + # change the scenario date and check the generated snippet + vehicles2 = find_child( "input.generate[data-id='vehicles_2']" ) def do_test( month, year, expected ): """Set the date and check the vehicle snippet.""" dismiss_notifications() select_tab( "scenario" ) set_template_params( { "SCENARIO_DATE": "{:02d}/01/{}".format(month,year) } ) select_tab( "ob2" ) - submit = find_child( "input.generate[data-id='vehicles_2']" ) - submit.click() + vehicles2.click() buf = get_clipboard() mo = re.search( r"^- capabilities: (.*)$", buf, re.MULTILINE ) assert mo.group(1) == expected - do_test( 1, 1940, '"sM8\u2020"' ) do_test( 1, 1943, '"sM8\u2020"' ) do_test( 2, 1943, '"HE7" "sM8\u2020"' ) diff --git a/vasl_templates/webapp/tests/test_vo_reports.py b/vasl_templates/webapp/tests/test_vo_reports.py index f95ede6..299ef9f 100644 --- a/vasl_templates/webapp/tests/test_vo_reports.py +++ b/vasl_templates/webapp/tests/test_vo_reports.py @@ -75,7 +75,7 @@ def test_vo_reports( webapp, webdriver ): fname = os.path.join( check_dir, fname ) assert open(fname,"r",encoding="utf-8").read() == report -# --------------------------------------------------------------------- +# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - def get_vo_report( webapp, webdriver, nat, vo_type, year ): """Get a vehicle/ordnance report. diff --git a/vasl_templates/webapp/tests/utils.py b/vasl_templates/webapp/tests/utils.py index e8e4d93..bcacb16 100644 --- a/vasl_templates/webapp/tests/utils.py +++ b/vasl_templates/webapp/tests/utils.py @@ -4,10 +4,12 @@ import os import urllib.request import json import time +import re from PyQt5.QtWidgets import QApplication from selenium.webdriver.support.ui import Select from selenium.webdriver.common.keys import Keys +from selenium.webdriver.common.action_chains import ActionChains from selenium.common.exceptions import NoSuchElementException, StaleElementReferenceException # standard templates @@ -45,28 +47,27 @@ def for_each_template( func ): #pylint: disable=too-many-branches for tab_id,template_ids in _STD_TEMPLATES.items(): for template_id in template_ids: select_tab( tab_id ) + orig_template_id = template_id if template_id == "scenario_notes": - template_id2 = "scenario_note" + template_id = "scenario_note" elif template_id.startswith( "ob_setup_" ): - template_id2 = "ob_setup" + template_id = "ob_setup" elif template_id.startswith( "ob_note_" ): - template_id2 = "ob_note" + template_id = "ob_note" elif template_id.startswith( "vehicles_" ): - template_id2 = "vehicles" + template_id = "vehicles" elif template_id.startswith( "ordnance_" ): - template_id2 = "ordnance" - else: - template_id2 = template_id - func( template_id2, template_id ) - if template_id not in ("ob_setup_2","ob_note_2","vehicles_2","ordnance_2"): - templates_to_test.remove( template_id2 ) + template_id = "ordnance" + func( template_id, orig_template_id ) + if orig_template_id not in ("ob_setup_2","ob_note_2","vehicles_2","ordnance_2"): + templates_to_test.remove( template_id ) # test the nationality-specific templates # NOTE: The buttons are the same on the OB1 and OB2 tabs, so we only test for player 1. + player1_sel = Select( find_child( "select[name='PLAYER_1']" ) ) for nat,template_ids in _NAT_TEMPLATES.items(): select_tab( "scenario" ) - sel = Select( find_child( "select[name='PLAYER_1']" ) ) - sel.select_by_value( nat ) + player1_sel.select_by_value( nat ) select_tab( "ob1" ) for template_id in template_ids: func( template_id, template_id ) @@ -95,14 +96,17 @@ def select_menu_option( menu_id ): def set_template_params( params ): #pylint: disable=too-many-branches """Set template parameters.""" + def add_sortable_entries( sortable, entries ): + """Add simple notes to a sortable.""" + for entry in entries: + add_simple_note( sortable, entry.get("caption",""), entry.get("width","") ) + for key,val in params.items(): # check for scenario notes (these require special handling) if key == "SCENARIO_NOTES": # add them in (nb: we don't consider any existing scenario notes) - from vasl_templates.webapp.tests.test_snippets import _add_scenario_note #pylint: disable=cyclic-import - for entry in val: - _add_scenario_note( _webdriver, entry.get("caption",""), entry.get("width","") ) + add_sortable_entries( find_child("#scenario_notes-sortable"), val ) continue # check for SSR's (these require special handling) @@ -113,22 +117,12 @@ def set_template_params( params ): #pylint: disable=too-many-branches add_ssr( _webdriver, ssr ) continue - # check for OB setups (these require special handling) - if key in ("OB_SETUPS_1","OB_SETUPS_2"): - # add them in (nb: we don't consider any existing OB setup's) - from vasl_templates.webapp.tests.test_ob import add_ob_setup #pylint: disable=cyclic-import - player_id = int( key[-1] ) - for entry in val: - add_ob_setup( _webdriver, player_id, entry.get("caption",""), entry.get("width","") ) - continue - - # check for OB notes (these require special handling) - if key in ("OB_NOTES_1","OB_NOTES_2"): - from vasl_templates.webapp.tests.test_ob import add_ob_note #pylint: disable=cyclic-import - # add them in (nb: we don't consider any existing OB notes) - player_id = int( key[-1] ) - for entry in val: - add_ob_note( _webdriver, player_id, entry.get("caption",""), entry.get("width","") ) + # check for OB setups/notes (these require special handling) + if key in ("OB_SETUPS_1","OB_SETUPS_2","OB_NOTES_1","OB_NOTES_2"): + # add them in (nb: we don't consider any existing OB setup/note's) + mo = re.search( r"^(.*)_(\d)$", key ) + sortable = find_child( "#{}-sortable_{}".format( mo.group(1).lower(), mo.group(2) ) ) + add_sortable_entries( sortable, val ) continue # check for vehicles/ordnance (these require special handling) @@ -168,6 +162,70 @@ def get_nationalities( webapp ): # --------------------------------------------------------------------- +def add_simple_note( sortable, caption, width ): + """Add a new simple note to a sortable.""" + edit_simple_note( sortable, None, caption, width ) + +def edit_simple_note( sortable, entry_no, caption, width ): + """Edit a simple note in a sortable.""" + + # figure out if we're creating a new entry, or editing an existing one + if entry_no is None: + # create a new entry + add_button = find_sortable_helper( sortable, "add" ) + add_button.click() + else: + # edit an existing entry + elems = find_children( "li", sortable ) + ActionChains(_webdriver).double_click( elems[entry_no] ).perform() + + # edit the note + if caption is not None: + elem = find_child( "#edit-simple_note textarea" ) + elem.clear() + elem.send_keys( caption ) + if width is not None: + elem = find_child( "#edit-simple_note input[type='text']" ) + elem.clear() + elem.send_keys( width ) + click_dialog_button( "OK" ) + if caption == "": + # an empty caption will delete the entry - confirm the deletion + click_dialog_button( "OK" ) + +# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + +def get_sortable_entry_text( sortable ): + """Get the text for each entry in a sortable.""" + return [ c.text for c in find_children("li", sortable) ] + +def get_sortable_entry_count( sortable ): + """Return the number of entries in a sortable.""" + return len( find_children( "li", sortable ) ) + +def generate_sortable_entry_snippet( sortable, entry_no ): + """Generate the snippet for a sortable entry.""" + elems = find_children( "li input[type='button']", sortable ) + elems[entry_no].click() + return get_clipboard() + +def drag_sortable_entry_to_trash( sortable, entry_no ): + """Draw a sortable entry to the trash.""" + trash = find_sortable_helper( sortable, "trash" ) + elems = find_children( "li", sortable ) + ActionChains(_webdriver).drag_and_drop( elems[entry_no], trash ).perform() + +def find_sortable_helper( sortable, tag ): + """Find a sortable's helper element.""" + sortable_id = sortable.get_attribute( "id" ) + mo = re.search( r"^(.+)-sortable(_\d)?$", sortable_id ) + helper_id = "#{}-{}".format( mo.group(1), tag ) + if mo.group(2): + helper_id += mo.group(2) + return find_child( helper_id ) + +# --------------------------------------------------------------------- + def get_stored_msg( msg_id ): """Get a message stored for us by the front-end.""" elem = find_child( "#"+msg_id ) @@ -189,6 +247,7 @@ def set_stored_msg( msg_id, val ): def find_child( sel, parent=None ): """Find a single child element.""" try: + # NOTE: I tried caching these results, but it didn't help the tests run any faster :-( return (parent if parent else _webdriver).find_element_by_css_selector( sel ) except NoSuchElementException: return None