""" Test HTML snippet generation. """
import re
import base64
import time
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_user_settings import set_user_settings, SCENARIO_IMAGES_SOURCE_THIS_PROGRAM
from vasl_templates.webapp.tests.utils import \
init_webapp, select_tab, find_snippet_buttons, set_template_params, wait_for, wait_for_clipboard, wait_for_elem, \
get_stored_msg, set_stored_msg_marker, find_child, find_children, find_sortable_helper, \
for_each_template, add_simple_note, edit_simple_note, click_dialog_button, \
load_trumbowyg, unload_trumbowyg, get_trumbowyg_editor, \
get_sortable_entry_count, generate_sortable_entry_snippet, drag_sortable_entry_to_trash, \
new_scenario, set_scenario_date, set_player
from vasl_templates.webapp.tests.test_scenario_persistence import load_scenario
# ---------------------------------------------------------------------
def test_snippet_ids( webapp, webdriver ):
"""Check that snippet ID's are generated correctly."""
# initialize
webapp.control_tests.set_data_dir( "{REAL}" )
init_webapp( webapp, webdriver, scenario_persistence=1 )
# load a scenario (so that we get some sortable's)
load_scenario( {
"COMPASS": "left",
"SCENARIO_NOTES": [ { "caption": "Scenario note #1" } ],
"OB_SETUPS_1": [ { "caption": "OB setup note #1" } ],
"OB_NOTES_1": [ { "caption": "OB note #1" } ],
"OB_SETUPS_2": [ { "caption": "OB setup note #2" } ],
"OB_NOTES_2": [ { "caption": "OB note #2" } ],
} )
def check_snippet( btn ):
"""Generate a snippet and check that it has an ID."""
btn.click()
wait_for_clipboard( 2, "".format( expected ),
"width: 123px",
"modified content",
] ), re.DOTALL )
wait_for_clipboard( 2, expected )
click_dialog_button( "Cancel" )
click_dialog_button( "OK" )
def test_new_simple_note( sortable, expected ) :
# add a new simple note
find_sortable_helper( sortable, "add" ).click()
elem = find_child( ".ui-dialog.edit-simple_note .trumbowyg-editor" )
load_trumbowyg( elem, "new content" )
elem = find_child( ".ui-dialog.edit-simple_note input[name='width']" )
if elem.is_displayed():
elem.clear()
elem.send_keys( "789px" )
# generate the snippet
click_dialog_button( "Snippet", contains=True )
if isinstance( expected, str ):
# NOTE: We also check that the snippet ID is correct.
expected = re.compile( ".*".join( [
"".format( expected ),
"width: 789px",
"new content",
] ), re.DOTALL )
wait_for_clipboard( 2, expected )
click_dialog_button( "Cancel" )
click_dialog_button( "OK" )
# test scenario notes
sortable = find_child( "#scenario_notes-sortable" )
test_existing_simple_note( sortable, 1, "scenario_note.2" )
test_new_simple_note( sortable, "scenario_note.3" )
# test SSR's
sortable = find_child( "#ssr-sortable" )
test_existing_simple_note( sortable, 1, re.compile( ".*".join( [
"",
"width: 222px",
r'
\s*- \s*SSR #1\s*
- \s*modified content\s*
',
] ), re.DOTALL ) )
test_new_simple_note( sortable, re.compile( ".*".join( [
"",
"width: 222px",
r'\s*- \s*SSR #1\s*
- \s*SSR #2\s*
- \s*new content\s*
',
] ), re.DOTALL ) )
# test OB setups
select_tab( "ob1" )
sortable = find_child( "#ob_setups-sortable_1" )
test_existing_simple_note( sortable, 1, "german/ob_setup_1.2" )
test_new_simple_note( sortable, "german/ob_setup_1.3" )
# test OB setups
select_tab( "ob2" )
sortable = find_child( "#ob_notes-sortable_2" )
test_existing_simple_note( sortable, 1, "russian/ob_note_2.2" )
test_new_simple_note( sortable, "russian/ob_note_2.3" )
# ---------------------------------------------------------------------
def test_edit_templates( webapp, webdriver ):
"""Test editing templates."""
# initialize
webapp.control_tests.set_vo_notes_dir( "{TEST}" )
init_webapp( webapp, webdriver, scenario_persistence=1, edit_template_links=1 )
load_scenario( {
"TURN_TRACK": { "NTURNS": 3 },
"COMPASS": "down",
} )
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 ):
"""Edit a template."""
elem = find_child( "#edit-template textarea" )
elem.clear()
elem.send_keys( "EDITED TEMPLATE: {}".format( template_id ) )
elem.send_keys( Keys.ESCAPE )
def test_template( template_id, orig_template_id ):
"""Test editing a template."""
if template_id in ("scenario_note","ob_setup","ob_note"):
return # nb: these require special handling (done below)
if template_id in ("ob_vehicle_note","ob_ordnance_note"):
return # nb: we currently don't support editing these in the UI
# edit the template
webdriver.execute_script( "$(arguments[0]).click();",
find_child( "a._edit-template-link_[data-id='{}']".format( template_id ) )
)
edit_template( orig_template_id )
# check that the new template is being used
elem = find_child( "button.generate[data-id='{}']".format( orig_template_id ) )
elem.click()
wait_for_clipboard( 2, "EDITED TEMPLATE: {}".format( orig_template_id ) )
for_each_template( test_template )
# customize the SCENARIO NOTE template
select_tab( "scenario" )
webdriver.execute_script( "$(arguments[0]).click();",
find_child( "a._edit-template-link_[data-id='scenario_note']" )
)
edit_template( "scenario_note" )
# check that the new template is being used
sortable = find_child( "#scenario_notes-sortable" )
add_simple_note( sortable, "scenario note (ignored)", None )
elem = find_child( "li img.snippet", sortable )
elem.click()
wait_for_clipboard( 2, "EDITED TEMPLATE: scenario_note" )
# customize the OB SETUP template
select_tab( "ob1" )
webdriver.execute_script( "$(arguments[0]).click();",
find_child( "a._edit-template-link_[data-id='ob_setup']" )
)
edit_template( "ob_setup" )
# check that the new template is being used
for player_no in range(1,2+1):
select_tab( "ob{}".format( player_no ) )
sortable = ob_setups[ player_no ]
add_simple_note( sortable, "ob setup (ignored)", None )
elem = find_child( "li img.snippet", sortable )
elem.click()
wait_for_clipboard( 2, "EDITED TEMPLATE: ob_setup" )
# customize the OB NOTE template
select_tab( "ob2" )
webdriver.execute_script( "$(arguments[0]).click();",
find_child( "a._edit-template-link_[data-id='ob_note']" )
)
edit_template( "ob_note" )
# check that the new template is being used
for player_no in range(1,2+1):
select_tab( "ob{}".format( player_no ) )
sortable = ob_notes[ player_no ]
add_simple_note( sortable, "ob note (ignored)", None )
elem = find_child( "li img.snippet", sortable )
elem.click()
wait_for_clipboard( 2, "EDITED TEMPLATE: ob_note" )
# ---------------------------------------------------------------------
# NOTE: These tests are seeing the same problem the WebDriver stress-test was seeing: the shift-click
# on the snippet button is sometimes being interpreted as a request to edit the sortable entry.
# However, the workaround we implemented in that script (dismissing the dialog) doesn't work here,
# and I just couldn't get things to work (not even reloading the page each time helped) :-(
@pytest.mark.skipif(
pytest_options.webdriver == "firefox",
reason="Selenium problems (?) cause these tests to fail under Firefox."
)
def test_snippet_images( webapp, webdriver ):
"""Test generating snippet images."""
# initialize
webapp.control_tests.set_vo_notes_dir( "{TEST}" )
init_webapp( webapp, webdriver, scenario_persistence=1, snippet_image_persistence=1 )
# check if there is a webdriver configured
remote_app_config = webapp.control_tests.get_app_config()
if "WEBDRIVER_PATH" not in remote_app_config:
return
# load a test scenario
load_scenario( {
"PLAYER_1": "german", "PLAYER_2": "russian",
"SCENARIO_NAME": "test scenario", "SCENARIO_DATE": "1940-01-01", "SCENARIO_LOCATION": "somewhere",
"SCENARIO_NOTES": [ { "caption": "Scenario note #1" } ],
"VICTORY_CONDITIONS": "win at all costs!",
"SSR": [ "a test ssr" ],
"OB_SETUPS_1": [ { "caption": "OB setup note #1" } ],
"OB_NOTES_1": [ { "caption": "OB note #1" } ],
"OB_VEHICLES_1": [ { "name": "a german vehicle" } ],
"OB_ORDNANCE_1": [ { "name": "a german ordnance" } ],
"OB_SETUPS_2": [ { "caption": "OB setup note #2" } ],
"OB_NOTES_2": [ { "caption": "OB note #2" } ],
"OB_VEHICLES_2": [ { "name": "a russian vehicle" } ],
"OB_ORDNANCE_2": [ { "name": "a russian ordnance" } ],
} )
def do_test( snippet_btn, expected_fname ): #pylint: disable=missing-docstring
# clear the return buffer
ret_buffer = find_child( "#_snippet-image-persistence_" )
assert ret_buffer.tag_name == "textarea"
webdriver.execute_script( "arguments[0].value = arguments[1]", ret_buffer, "" )
# shift-click the snippet button
ActionChains( webdriver ).key_down( Keys.SHIFT ).click( snippet_btn ).perform()
ActionChains( webdriver ).key_up( Keys.SHIFT ).perform()
# wait for the snippet image to be generated
wait_for( 20, lambda: ret_buffer.get_attribute( "value" ) )
fname, img_data = ret_buffer.get_attribute( "value" ).split( "|", 1 )
img_data = base64.b64decode( img_data )
# check the results
assert fname == expected_fname
last_snippet_image = webapp.control_tests.get_last_snippet_image()
assert img_data == last_snippet_image
def do_simple_test( template_id, expected_fname ): #pylint: disable=missing-docstring
btn = find_child( "button.generate[data-id='{}']".format( template_id ) )
do_test( btn, expected_fname )
def do_sortable_test( sortable_id, expected_fname ): #pylint: disable=missing-docstring
entries = find_children( "#{} li".format( sortable_id ) )
assert len(entries) == 1
btn = find_child( "img.snippet", entries[0] )
do_test( btn, expected_fname )
# do the tests
do_simple_test( "scenario", "scenario.png" )
do_simple_test( "players", "players.png" )
do_sortable_test( "scenario_notes-sortable", "scenario note.1.png" )
do_simple_test( "victory_conditions", "victory conditions.png" )
do_simple_test( "ssr", "ssr.png" )
# do the tests
select_tab( "ob1" )
do_sortable_test( "ob_setups-sortable_1", "ob setup 1.1.png" )
do_sortable_test( "ob_notes-sortable_1", "ob note 1.1.png" )
do_sortable_test( "ob_vehicles-sortable_1", "a german vehicle.png" )
do_sortable_test( "ob_ordnance-sortable_1", "a german ordnance.png" )
# do the tests
select_tab( "ob2" )
do_sortable_test( "ob_setups-sortable_2", "ob setup 2.1.png" )
do_sortable_test( "ob_notes-sortable_2", "ob note 2.1.png" )
do_sortable_test( "ob_vehicles-sortable_2", "a russian vehicle.png" )
do_sortable_test( "ob_ordnance-sortable_2", "a russian ordnance.png" )
# ---------------------------------------------------------------------
def test_player_flags_in_trumbowyg( webapp, webdriver ):
"""Test inserting images for player flags into Trumbowyg HTML editor controls."""
# initialize
webapp.control_tests.set_app_config_val( "TRUMBOWYG_BUTTONS_VICTORY_CONDITIONS",
'[ "flags", "viewHTML" ]'
)
init_webapp( webapp, webdriver )
def check_flags_dropdown( expected ):
dropdown = find_child( "#panel-vc .trumbowyg-dropdown-flags" )
nats = [
img.get_attribute( "data-nat" )
for img in find_children( "button img", dropdown )
]
assert nats[ 0 : len(expected) ] == expected
# check the initial state of the flags dropdown
check_flags_dropdown( [ "german", "russian", "american", "british" ] )
# change the players, check the flags dropdown
set_player( 1, "british" )
set_player( 2, "french" )
check_flags_dropdown( [ "british", "french", "american", "burmese" ] )
# load some content into the Victory Conditions and position the cursor
editor = get_trumbowyg_editor( "VICTORY_CONDITIONS" )
editor.send_keys( "abcxyz" )
for _ in range( 3 ):
editor.send_keys( Keys.LEFT )
def insert_flag( nat ):
find_child( "#panel-vc .trumbowyg-flags-button" ).click()
wait_for_elem( 2, "#panel-vc .trumbowyg-dropdown-flags" )
find_child( "button.trumbowyg-{}-small-dropdown-button".format( nat ) ).click()
def wait_for_flag( expected ):
if expected.search( unload_trumbowyg( editor ) ):
return True
time.sleep( 0.1 )
return False
# insert an online flag
insert_flag( "japanese" )
wait_for( 2, lambda: wait_for_flag(
re.compile( 'abcxyz' )
) )
# configure local images, then add another image
# NOTE: Opening the User Settings dialog makes the cursor move to the start of the Trumboyg content.
set_user_settings( { "scenario-images-source": SCENARIO_IMAGES_SOURCE_THIS_PROGRAM } )
insert_flag( "american" )
wait_for( 2, lambda: wait_for_flag(
re.compile( r'abc