예제 #1
0
def test_include_flags_in_snippets(webapp, webdriver):
    """Test including flags in snippets."""

    # initialize
    webapp.control_tests.set_data_dir("{REAL}")
    init_webapp(webapp, webdriver)

    # prepare the scenario
    set_player(1, "german")
    select_tab("ob1")
    sortable = find_child("#ob_setups-sortable_1")
    add_simple_note(sortable, "OB setup note", None)

    # enable "show flags in snippets"
    select_menu_option("user_settings")
    elem = find_child(
        ".ui-dialog.user-settings input[name='include-flags-in-snippets']")
    assert not elem.is_selected()
    elem.click()
    click_dialog_button("OK")
    _check_cookies(webdriver, "include-flags-in-snippets", True)

    # make sure that it took effect
    ob_setup_snippet_btn = find_child("li img.snippet", sortable)
    ob_setup_snippet_btn.click()
    wait_for_clipboard(2, "/flags/german", contains=True)

    # make sure it also affects vehicle/ordnance snippets
    ob_vehicles_snippet_btn = find_child(
        "button.generate[data-id='ob_vehicles_1']")
    ob_vehicles_snippet_btn.click()
    wait_for_clipboard(2, "/flags/german", contains=True)
    ob_ordnance_snippet_btn = find_child(
        "button.generate[data-id='ob_ordnance_1']")
    ob_ordnance_snippet_btn.click()
    wait_for_clipboard(2, "/flags/german", contains=True)

    # disable "show flags in snippets"
    select_menu_option("user_settings")
    elem = find_child(
        ".ui-dialog.user-settings input[name='include-flags-in-snippets']")
    assert elem.is_selected()
    elem.click()
    click_dialog_button("OK")
    _check_cookies(webdriver, "include-flags-in-snippets", False)

    # make sure that it took effect
    ob_setup_snippet_btn.click()
    wait_for_clipboard(2, "/flags/german", contains=False)

    # make sure it also affects vehicle/ordnance snippets
    ob_vehicles_snippet_btn.click()
    wait_for_clipboard(2, "/flags/german", contains=False)
    ob_ordnance_snippet_btn.click()
    wait_for_clipboard(2, "/flags/german", contains=False)
예제 #2
0
def _enable_vo_no_notes_as_images(enable):
    """Enable/disable vehicle/ordnance notes as images."""
    select_menu_option("user_settings")
    elem = find_child(
        ".ui-dialog.user-settings input[name='vo-notes-as-images']")
    if (elem.is_selected() and not enable) or (not elem.is_selected()
                                               and enable):
        elem.click()
        click_dialog_button("OK")
    else:
        click_dialog_button("Cancel")
예제 #3
0
def test_multiple_images(webapp, webdriver):
    """Test handling of VASL counters that have multiple images."""

    # initialize
    webapp.control_tests \
        .set_data_dir( "{REAL}" ) \
        .set_vasl_version( "random", None )
    init_webapp(webapp, webdriver, scenario_persistence=1)

    # load the test scenario
    load_scenario({
        "PLAYER_1": "british",
        "OB_VEHICLES_1": [{
            "name": "2pdr Portee"
        }],
    })

    # configure the user settings
    set_user_settings({
        "scenario-images-source": SCENARIO_IMAGES_SOURCE_INTERNET,
        "include-vasl-images-in-snippets": True,
    })

    # generate a snippet for the vehicle (using the default image)
    select_tab("ob1")
    btn = find_child("button[data-id='ob_vehicles_1']")
    btn.click()
    wait_for_clipboard(
        2,
        re.compile(
            r'<img src="https://raw.githubusercontent.com/.+/br/vehicles/portee.gif"'
        ))

    # select the second image for the vehicle
    sortable = find_child("#ob_vehicles-sortable_1")
    elems = find_children("li", sortable)
    assert len(elems) == 1
    ActionChains(webdriver).double_click(elems[0]).perform()
    btn = wait_for_elem(2, "#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()
    click_dialog_button("OK")

    # generate a snippet for the vehicle (using the new image)
    btn = find_child("button[data-id='ob_vehicles_1']")
    btn.click()
    wait_for_clipboard(
        2,
        re.compile(
            r'<img src="https://raw.githubusercontent.com/.+/br/vehicles/portee0.gif"'
        ))
예제 #4
0
def test_vo_notes_as_images(webapp, webdriver):
    """Test showing vehicle/ordnance notes as HTML/images."""

    # initialize
    webapp.control_tests.set_vo_notes_dir("{TEST}")
    init_webapp(webapp, webdriver, scenario_persistence=1)

    # load the test vehicle
    load_scenario({
        "PLAYER_1": "greek",
        "OB_VEHICLES_1": [{
            "name": "HTML note"
        }],
    })
    select_tab("ob1")

    def check_snippet(expected):
        """Generate and check the vehicle note snippet."""
        sortable = find_child("#ob_vehicles-sortable_1")
        elems = find_children("li", sortable)
        assert len(elems) == 1
        btn = find_child("img.snippet", elems[0])
        btn.click()
        contains = True if isinstance(expected, str) else None
        wait_for_clipboard(2, expected, contains=contains)

    # generate the vehicle snippet (should get the raw HTML)
    check_snippet("This is an HTML vehicle note (202).")

    # enable "show vehicle/ordnance notes as images"
    select_menu_option("user_settings")
    elem = find_child(
        ".ui-dialog.user-settings input[name='vo-notes-as-images']")
    assert not elem.is_selected()
    elem.click()
    click_dialog_button("OK")
    _check_cookies(webdriver, "vo-notes-as-images", True)

    # generate the vehicle snippet (should get a link to return an image)
    check_snippet(re.compile(r"http://.+?:\d+/vehicles/greek/note/202"))

    # disable "show vehicle/ordnance notes as images"
    select_menu_option("user_settings")
    elem = find_child(
        ".ui-dialog.user-settings input[name='vo-notes-as-images']")
    assert elem.is_selected()
    elem.click()
    click_dialog_button("OK")
    _check_cookies(webdriver, "vo-notes-as-images", False)

    # generate the vehicle snippet (should get the raw HTML)
    check_snippet("This is an HTML vehicle note (202).")
예제 #5
0
    def do_test(tab_id, param):
        """Test checking for a dirty scenario."""

        # change the specified field
        check_is_dirty(False)
        select_tab(tab_id)
        state = change_field(param)
        check_is_dirty(True)

        # make sure we get asked to confirm a "new scenario" operation
        select_menu_option("new_scenario")
        wait_for(2, lambda: find_child("#ask") is not None)
        elem = find_child("#ask")
        assert "This scenario has been changed" in elem.text

        # cancel the confirmation request, make sure the change we made is still there
        click_dialog_button("Cancel")
        select_tab(tab_id)
        check_field(param, state)
        check_is_dirty(True)

        # revert the change
        revert_field(param, state)
        check_is_dirty(False)

        # we should now be able to reset the scenario without a confirmation
        _ = set_stored_msg_marker("_last-info_")
        select_menu_option("new_scenario")
        wait_for(
            2,
            lambda: get_stored_msg("_last-info_") == "The scenario was reset.")

        # change the field again
        select_tab(tab_id)
        state = change_field(param)
        check_is_dirty(True)

        # make sure we get asked to confirm a "load scenario" operation
        select_menu_option("load_scenario")
        wait_for(2, lambda: find_child("#ask") is not None)
        elem = find_child("#ask")
        assert "This scenario has been changed" in elem.text

        # cancel the confirmation request, make sure the change we made is still there
        click_dialog_button("Cancel")
        select_tab(tab_id)
        check_field(param, state)
        check_is_dirty(True)

        # revert the change
        revert_field(param, state)
        check_is_dirty(False)
예제 #6
0
def test_hide_unavailable_ma_notes(webapp, webdriver):
    """Test showing/hiding unavailable multi-applicable notes."""

    # initialize
    webapp.control_tests.set_vo_notes_dir("{TEST}")
    init_webapp(webapp, webdriver, scenario_persistence=1)

    # load the test vehicle
    load_scenario({
        "PLAYER_1": "german",
        "OB_VEHICLES_1": [{
            "name": "missing multi-applicable note"
        }]
    })
    select_tab("ob1")

    def test_ma_notes(ma_note_q_present):  #pylint: disable=missing-docstring
        expected = [("A", 'German Multi-Applicable Vehicle Note "A".')]
        if ma_note_q_present:
            expected.append(("Q", "Unavailable."))
        btn = find_child("button[data-id='ob_vehicles_ma_notes_1']")
        btn.click()
        wait_for_clipboard(2, expected, transform=extract_ma_notes)

    # generate the multi-applicable notes
    test_ma_notes(True)

    # enable "hide unavailable multi-applicable notes"
    select_menu_option("user_settings")
    elem = find_child(
        ".ui-dialog.user-settings input[name='hide-unavailable-ma-notes']")
    assert not elem.is_selected()
    elem.click()
    click_dialog_button("OK")
    _check_cookies(webdriver, "hide-unavailable-ma-notes", True)

    # generate the multi-applicable notes
    test_ma_notes(False)

    # disable "hide unavailable multi-applicable notes"
    select_menu_option("user_settings")
    elem = find_child(
        ".ui-dialog.user-settings input[name='hide-unavailable-ma-notes']")
    assert elem.is_selected()
    elem.click()
    click_dialog_button("OK")
    _check_cookies(webdriver, "hide-unavailable-ma-notes", False)

    # generate the multi-applicable notes
    test_ma_notes(True)
예제 #7
0
def set_user_settings(opts):
    """Configure the user settings."""
    select_menu_option("user_settings")
    for key, val in opts.items():
        if isinstance(val, bool):
            elem = find_child(
                ".ui-dialog.user-settings input[name='{}']".format(key))
            if (val and not elem.is_selected()) or (not val
                                                    and elem.is_selected()):
                elem.click()
        elif isinstance(val, int):
            elem = find_child(
                ".ui-dialog.user-settings select[name='{}']".format(key))
            select_droplist_val(Select(elem), val)
        else:
            assert False
    click_dialog_button("OK")
예제 #8
0
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" )
예제 #9
0
def test_include_vasl_images_in_snippets(webapp, webdriver):
    """Test including VASL counter images in snippets."""

    # initialize
    webapp.control_tests.set_data_dir("{REAL}")
    init_webapp(webapp, webdriver)
    set_user_settings(
        {"scenario-images-source": SCENARIO_IMAGES_SOURCE_THIS_PROGRAM})

    # add a vehicle
    set_player(1, "german")
    add_vo(webdriver, "vehicles", 1, "PzKpfw IB")

    # enable "show VASL images in snippets"
    select_menu_option("user_settings")
    elem = find_child(
        ".ui-dialog.user-settings input[name='include-vasl-images-in-snippets']"
    )
    assert not elem.is_selected()
    elem.click()
    click_dialog_button("OK")
    _check_cookies(webdriver, "include-vasl-images-in-snippets", True)

    # make sure that it took effect
    snippet_btn = find_child("button[data-id='ob_vehicles_1']")
    snippet_btn.click()
    wait_for_clipboard(2, "/counter/2524/front", contains=True)

    # disable "show VASL images in snippets"
    select_menu_option("user_settings")
    elem = find_child(
        ".ui-dialog.user-settings input[name='include-vasl-images-in-snippets']"
    )
    assert elem.is_selected()
    elem.click()
    click_dialog_button("OK")
    _check_cookies(webdriver, "include-vasl-images-in-snippets", False)

    # make sure that it took effect
    snippet_btn.click()
    wait_for_clipboard(2, "/counter/2524/front", contains=False)
예제 #10
0
    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", find_child(".ui-dialog.ask") )
        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", find_child(".ui-dialog.ask") )

        # make sure the vehicle/ordnance was added to the player's OB
        assert get_sortable_vo_names( sortable ) == [ vo_name, vo_name ]
예제 #11
0
def test_elite( webapp, webdriver ): #pylint: disable=too-many-statements
    """Test elite vehicles/ordnance."""

    # initialize
    webapp.control_tests.set_data_dir( "{REAL}" )
    init_webapp( webapp, webdriver, scenario_persistence=1 )

    def get_sortable_elem():
        """Find the sortable element for the test vehicle."""
        sortable = find_child( "#ob_vehicles-sortable_1" )
        elems = find_children( "li", sortable )
        assert len(elems) == 1
        return elems[0]
    def check_elite( expected, custom ):
        """Check the elite status of the vehicle in the main UI."""
        vo_name = find_child( ".vo-name", get_sortable_elem() ).text
        caps = [ c.text for c in find_children(".vo-capability",get_sortable_elem()) ]
        if expected:
            assert vo_name.endswith( "\u24ba" )
            expected = [ "H9", "s10", "sD7", "CS 5" ]
            if custom:
                expected.append( "HE11" )
            assert caps == expected
        else:
            assert "\u24ba" not in vo_name
            expected = [ "H8", "s9", "sD7", "CS 5" ]
            if custom:
                expected.append( "HE10" )
            assert caps == expected
    def check_elite2( expected, custom ):
        """Check the elite status of the vehicle in the edit dialog."""
        vo_name = find_child( "#edit-vo .header .vo-name" ).text
        caps = [ c.get_attribute("value") for c in find_children("#vo_capabilities-sortable input[type='text']") ]
        if expected:
            assert vo_name.endswith( "\u24ba" )
            expected = [ "H9", "s10", "sD7", "CS 5" ]
            if custom:
                expected.append( "HE11" )
            assert caps == expected
        else:
            assert "\u24ba" not in vo_name
            expected = [ "H8", "s9", "sD7", "CS 5" ]
            if custom:
                expected.append( "HE10" )
            assert caps == expected

    # load the scenario
    scenario_data = {
        "PLAYER_1": "german",
        "OB_VEHICLES_1": [ { "name": "PSW 233" } ], # H8 s9 sD7 CS 5
    }
    load_scenario( scenario_data )
    select_tab( "ob1" )

    # check that the vehicle was loaded non-elite
    check_elite( False, False )

    # add a custom capability
    ActionChains( webdriver ).double_click( get_sortable_elem() ).perform()
    elem = find_child( "#vo_capabilities-add" )
    elem.click()
    elems = find_children( "#vo_capabilities-sortable input[type='text']" )
    assert len(elems) == 5
    elems[4].send_keys( "HE10" )
    click_dialog_button( "OK" )

    # make the vehicle elite
    ActionChains( webdriver ).double_click( get_sortable_elem() ).perform()
    check_elite2( False, True )
    elem = find_child( "#edit-vo .capabilities .elite" )
    elem.click()
    check_elite2( True, True )
    click_dialog_button( "OK" )
    check_elite( True, True )

    # save the scenario, then reload it
    saved_scenario = save_scenario()
    assert len(saved_scenario["OB_VEHICLES_1"]) == 1
    assert saved_scenario["OB_VEHICLES_1"][0]["elite"]
    assert saved_scenario["OB_VEHICLES_1"][0]["custom_capabilities"] == \
        [ "H9", "s10", "sD7", "CS 5", "HE11" ]
    select_menu_option( "new_scenario" )
    load_scenario( saved_scenario )
    select_tab( "ob1" )
    check_elite( True, True )

    # make the vehicle non-elite
    ActionChains( webdriver ).double_click( get_sortable_elem() ).perform()
    check_elite2( True, True )
    elem = find_child( "#edit-vo .capabilities .elite" )
    elem.click()
    check_elite2( False, True )
    click_dialog_button( "OK" )
    check_elite( False, True )

    # save the scenario
    saved_scenario = save_scenario()
    assert len(saved_scenario["OB_VEHICLES_1"]) == 1
    assert "elite" not in saved_scenario["OB_VEHICLES_1"][0]
    assert saved_scenario["OB_VEHICLES_1"][0]["custom_capabilities"] == \
        [ "H8", "s9", "sD7", "CS 5", "HE10" ]

    # make the vehicle elite, remove the custom capability
    ActionChains( webdriver ).double_click( get_sortable_elem() ).perform()
    check_elite2( False, True )
    elem = find_child( "#edit-vo .capabilities .elite" )
    elem.click()
    check_elite2( True, True )
    elems = find_children( "#vo_capabilities-sortable li" )
    webdriver.execute_script( "arguments[0].scrollIntoView(true);", elems[4] )
    ActionChains( webdriver ).key_down( Keys.CONTROL ).click( elems[4] ).perform()
    ActionChains( webdriver ).key_up( Keys.CONTROL ).perform()
    click_dialog_button( "OK" )
    check_elite( True, False )

    # save the scenario, then reload it
    saved_scenario = save_scenario()
    assert len(saved_scenario["OB_VEHICLES_1"]) == 1
    assert saved_scenario["OB_VEHICLES_1"][0]["elite"]
    assert saved_scenario["OB_VEHICLES_1"][0]["custom_capabilities"] == [ "H9", "s10", "sD7", "CS 5" ]
    select_menu_option( "new_scenario" )
    load_scenario( saved_scenario )
    select_tab( "ob1" )
    check_elite( True, False )

    # make the vehicle non-elite
    ActionChains( webdriver ).double_click( get_sortable_elem() ).perform()
    check_elite2( True, False )
    elem = find_child( "#edit-vo .capabilities .elite" )
    elem.click()
    check_elite2( False, False )
    click_dialog_button( "OK" )
    check_elite( False, False )

    # save the scenario
    saved_scenario = save_scenario()
    assert len(saved_scenario["OB_VEHICLES_1"]) == 1
    assert "elite" not in saved_scenario["OB_VEHICLES_1"][0]
    assert "custom_capabilities" not in saved_scenario["OB_VEHICLES_1"][0]
예제 #12
0
def test_capability_updates_in_ui( webapp, webdriver ):
    """Check that capabilities are updated in the UI correctly."""

    # initialize
    webapp.control_tests.set_data_dir( "{REAL}" )
    init_webapp( webapp, webdriver, scenario_persistence=1 )

    # load the scenario
    scenario_data = {
        "PLAYER_1": "german",
        "OB_VEHICLES_1": [ { "name": "PzKpfw 38(t)A" } ], # A4[1]/5[2] ; sD6 ; CS 4
        "OB_ORDNANCE_1": [ { "name": "3.7cm PaK 35/36" } ], # NT ; A4[1]/5[2]/4[3]/3[4] ; H6[9]†
        "PLAYER_2": "russian",
        "OB_VEHICLES_2": [ { "name": "Churchill III(b)" } ], # D6[J4]/7[5]† ; HE7[F3]/8[4+]† ; sD6[4+] ; sM8† ; CS 7
        "OB_ORDNANCE_2": [ { "name": "45mm PTP obr. 32" } ], # NT ; A4[2]/5[3]/6[4]/7[5]
    }
    scenario_data["OB_VEHICLES_1"].append( { "name": "PzJg I" } ) # A5[1]/6[2]/5[3]; HE7 ; CS 3
    load_scenario( scenario_data )

    sortables = [
        find_child( "#ob_vehicles-sortable_1" ),
        find_child( "#ob_ordnance-sortable_1" ),
        find_child( "#ob_vehicles-sortable_2" ),
        find_child( "#ob_ordnance-sortable_2" ),
    ]
    def check_capabilities( scenario_date, expected ):
        """Get the vehicle/ordnance capabilities from the UI."""
        # set the scenario date
        set_scenario_date( scenario_date )
        # check the vehicle/ordnance capabilities
        results = []
        for sortable in sortables:
            results.append( [] )
            vo_entries = find_children( "li", sortable )
            for vo_entry in vo_entries:
                capabilities = find_children( "span.vo-capability", vo_entry )
                results[-1].append( [ c.get_attribute("innerHTML") for c in capabilities ] )
        for row in expected:
            for i,entries in enumerate(row):
                row[i] = [ e for e in entries if e not in _IGNORE_CAPABILITIES ]
        assert results == expected

    # no scenario date => we should be showing the raw capabilities
    check_capabilities( None, [
        [
            [ "A4<sup>1</sup>5<sup>2</sup>", "sD6", "CS 4" ],
            [ "A5<sup>1</sup>6<sup>2</sup>5<sup>3</sup>", "HE7", "CS 3" ]
        ],
        [ [ "NT", "A4<sup>1</sup>5<sup>2</sup>4<sup>3</sup>3<sup>4</sup>", "H6[9]\u2020" ] ],
        [ [ "D6<sup>J4</sup>7<sup>5</sup>†", "HE7<sup>F3</sup>8<sup>4+</sup>\u2020", "sD6<sup>4+</sup>", "sM8\u2020", "CS 7" ] ], #pylint: disable=line-too-long
        [ [ "NT", "A4<sup>2</sup>5<sup>3</sup>6<sup>4</sup>7<sup>5</sup>" ] ]
    ] )

    # edit the PzJg I's capabilities (nb: this locks them in, and they should not change
    # regardless of what the scenario date is set to)
    select_tab( "ob1" )
    vehicles_sortable = find_child( "#ob_vehicles-sortable_1" )
    elems = find_children( "li", vehicles_sortable )
    assert len(elems) == 2
    ActionChains( webdriver ).double_click( elems[1] ).perform()
    elem = find_child( "#vo_capabilities-add" )
    elem.click()
    elems = find_children( "#vo_capabilities-sortable input[type='text']" )
    assert len(elems) == 4
    elems[3].send_keys( "foo!" )
    click_dialog_button( "OK" )

    # change the scenario date, check the capabilities
    select_tab( "scenario" )
    check_capabilities( "01/01/1940", [
        [
            [ "sD6", "CS 4" ],
            [ "A5<sup>1</sup>6<sup>2</sup>5<sup>3</sup>", "HE7", "CS 3", "foo!" ]
        ],
        [ [ "NT", "H6[9]\u2020" ] ],
        [ [ "sM8\u2020", "CS 7" ] ],
        [ [ "NT" ] ]
    ] )
    check_capabilities( "01/01/1941", [
        [
            [ "A4", "sD6", "CS 4" ] ,
            [ "A5<sup>1</sup>6<sup>2</sup>5<sup>3</sup>", "HE7", "CS 3", "foo!" ]
        ],
        [ [ "NT", "A4", "H6[9]\u2020" ] ],
        [ [ "sM8\u2020", "CS 7" ] ],
        [ [ "NT" ] ]
    ] )
    check_capabilities( "01/01/1942", [
        [
            [ "A5", "sD6", "CS 4" ],
            [ "A5<sup>1</sup>6<sup>2</sup>5<sup>3</sup>", "HE7", "CS 3", "foo!" ]
        ],
        [ [ "NT", "A5", "H6[9]\u2020" ] ],
        [ [ "sM8\u2020", "CS 7" ] ],
        [ [ "NT", "A4" ] ]
    ] )
    check_capabilities( "01/01/1943", [
        [
            [ "sD6", "CS 4" ],
            [ "A5<sup>1</sup>6<sup>2</sup>5<sup>3</sup>", "HE7", "CS 3", "foo!" ]
        ],
        [ [ "NT", "A4", "H6[9]\u2020" ] ],
        [ [ "sM8\u2020", "CS 7" ] ],
        [ [ "NT", "A5" ] ]
    ] )
    check_capabilities( "01/01/1944", [
        [
            [ "sD6", "CS 4" ],
            [ "A5<sup>1</sup>6<sup>2</sup>5<sup>3</sup>", "HE7", "CS 3", "foo!" ]
        ],
        [ [ "NT", "A3", "H6[9]\u2020" ] ],
        [ [ "HE8\u2020", "sD6", "sM8\u2020", "CS 7" ] ],
        [ [ "NT", "A6" ] ]
    ] )
    check_capabilities( "01/01/1945", [
        [
            [ "sD6", "CS 4" ],
            [ "A5<sup>1</sup>6<sup>2</sup>5<sup>3</sup>", "HE7", "CS 3", "foo!" ]
        ],
        [ [ "NT", "H6[9]\u2020" ] ],
        [ [ "D7\u2020", "HE8\u2020", "sD6", "sM8\u2020", "CS 7" ] ],
        [ [ "NT", "A7" ] ]
    ] )
예제 #13
0
def test_custom_comments( webapp, webdriver ): #pylint: disable=too-many-statements
    """Test custom comments."""

    # NOTE: Vehicle/ordnance comments are not capabilities, but they are managed in the same place
    # and the code is virtually identical, so it makes sense to put the test code here.

    # initialize
    init_webapp( webapp, webdriver, scenario_persistence=1 )

    # add a vehicle
    add_vo( webdriver, "vehicles", 1, "a commented german vehicle" )

    snippet_btn = find_child( "button[data-id='ob_vehicles_1']" )
    def extract_comments( clipboard ):
        """Extract the comments."""
        mo = re.search( r"^- comments: (.*)$", clipboard, re.MULTILINE )
        return mo.group(1) if mo else ""
    def check_snippet( expected ):
        """Check the vehicle's snippet."""
        snippet_btn.click()
        wait_for_clipboard( 2, expected, transform=extract_comments )
    def check_comments_in_dialog( expected ):
        """Check the vehicle's comments."""
        elems = find_children( "#vo_comments-sortable li" )
        elems2 = [ find_child("input[type='text']",c) for c in elems ]
        assert [ e.get_attribute("value") for e in elems2 ] == expected
        return elems

    # check the vehicle's snippet
    check_snippet( '"a comment" "another comment"' )

    # edit the vehicle's comments
    vehicles_sortable = find_child( "#ob_vehicles-sortable_1" )
    elems = find_children( "li", vehicles_sortable )
    assert len(elems) == 1
    ActionChains( webdriver ).double_click( elems[0] ).perform()
    elems = check_comments_in_dialog( [ "a comment", "another comment" ] )

    # edit one of the comments
    elem = find_child( "input[type='text']", elems[0] )
    elem.clear()
    elem.send_keys( "a comment (modified)" )

    # delete a comment
    ActionChains( webdriver ).key_down( Keys.CONTROL ).click( elems[1] ).perform()
    ActionChains( webdriver ).key_up( Keys.CONTROL ).perform()

    # add a new comment
    elem = find_child( "#vo_comments-add" )
    elem.click()
    elems = find_children( "#vo_comments-sortable input[type='text']" )
    assert len(elems) == 2
    elems[1].send_keys( "a <i>new</i> comment" )

    # save the changes and check the vehicle's snippet
    click_dialog_button( "OK" )
    check_snippet( '"a comment (modified)" "a <i>new</i> comment"' )

    # save the scenario
    saved_scenario = save_scenario()
    assert len(saved_scenario["OB_VEHICLES_1"]) == 1
    assert saved_scenario["OB_VEHICLES_1"][0]["custom_comments"] == [ "a comment (modified)", "a <i>new</i> comment" ]

    # reload the scenario, and check the vehicle's snippet
    select_menu_option( "new_scenario" )
    load_scenario( saved_scenario )
    select_tab( "ob1" )
    check_snippet( '"a comment (modified)" "a <i>new</i> comment"' )

    # make sure the comments are loaded correcly when editing the vehicle
    elems = find_children( "li", vehicles_sortable )
    assert len(elems) == 1
    ActionChains( webdriver ).double_click( elems[0] ).perform()
    elems = check_comments_in_dialog( [ "a comment (modified)", "a <i>new</i> comment" ] )

    # delete all comments
    for elem in elems:
        ActionChains( webdriver ).key_down( Keys.CONTROL ).click( elem ).perform()
        ActionChains( webdriver ).key_up( Keys.CONTROL ).perform()
    click_dialog_button( "OK" )
    check_snippet( "" )

    # save the scenario
    saved_scenario2 = save_scenario()
    assert len(saved_scenario2["OB_VEHICLES_1"]) == 1
    assert saved_scenario2["OB_VEHICLES_1"][0]["custom_comments"] == []

    # reload the scenario, and reset the vehicle's comments back to the default
    load_scenario( saved_scenario )
    select_tab( "ob1" )
    elems = find_children( "li", vehicles_sortable )
    assert len(elems) == 1
    ActionChains( webdriver ).double_click( elems[0] ).perform()
    btn = find_child( "#vo_comments-reset" )
    btn.click()
    click_dialog_button( "OK" )
    check_snippet( '"a comment" "another comment"' )

    # make sure the custom comments are no longer saved in the scenario
    saved_scenario2 = save_scenario()
    assert len(saved_scenario2["OB_VEHICLES_1"]) == 1
    assert "custom_comments" not in saved_scenario2["OB_VEHICLES_1"][0]

    # reload the scenario, and manually set the vehicle's comments to be the same as the default
    load_scenario( saved_scenario )
    select_tab( "ob1" )
    elems = find_children( "li", vehicles_sortable )
    assert len(elems) == 1
    ActionChains( webdriver ).double_click( elems[0] ).perform()
    elems = find_children( "#vo_comments-sortable input[type='text']" )
    assert len(elems) == 2
    elems[0].clear()
    elems[0].send_keys( "a comment" )
    elems[1].clear()
    elems[1].send_keys( "another comment" )
    click_dialog_button( "OK" )

    # make sure the custom comments are no longer saved in the scenario
    saved_scenario = save_scenario()
    assert len(saved_scenario["OB_VEHICLES_1"]) == 1
    assert "custom_comments" not in saved_scenario["OB_VEHICLES_1"][0]
def snippet_images_thread(webapp_url):
    """Test generating snippet images."""

    with WebDriver() as webdriver:

        # initialize
        webdriver = webdriver.driver
        init_webapp(webdriver, webapp_url,
                    ["snippet_image_persistence", "scenario_persistence"])

        # load a scenario (so that we get some sortable's)
        scenario_data = {
            "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"
            }],
        }
        load_scenario(scenario_data, webdriver)

        # locate all the "generate snippet" buttons
        snippet_btns = find_snippet_buttons(webdriver)
        tab_ids = list(snippet_btns.keys())

        while not shutdown_event.is_set():

            try:
                # clear the return buffer
                ret_buffer = find_child("#_snippet-image-persistence_",
                                        webdriver)
                assert ret_buffer.tag_name == "textarea"
                webdriver.execute_script("arguments[0].value = arguments[1]",
                                         ret_buffer, "")

                # generate a snippet
                tab_id = random.choice(tab_ids)
                btn = random.choice(snippet_btns[tab_id])
                log("Getting snippet image: {}", btn.get_attribute("data-id"))
                select_tab(tab_id, webdriver)
                start_time = time.time()
                ActionChains( webdriver ) \
                    .key_down( Keys.SHIFT ) \
                    .click( btn ) \
                    .key_up( Keys.SHIFT ) \
                    .perform()

                # wait for the snippet image to be generated
                wait_for(10 * thread_count,
                         lambda: ret_buffer.get_attribute("value"))
                _, img_data = ret_buffer.get_attribute("value").split("|", 1)
                elapsed_time = time.time() - start_time

                # update the stats
                with stats_lock:
                    stats["snippet image"][0] += 1
                    stats["snippet image"][1] += elapsed_time

                # FUDGE! Generating the snippet image for a sortable entry is sometimes interpreted as
                # a request to edit the entry (Selenium problem?) - we dismiss the dialog here and continue.
                dlg = find_child(".ui-dialog", webdriver)
                if dlg and dlg.is_displayed():
                    click_dialog_button("Cancel", webdriver)

            except (ConnectionRefusedError, ConnectionResetError,
                    http.client.RemoteDisconnected):
                if shutdown_event.is_set():
                    break
                raise

            # check the generated snippet
            img_data = base64.b64decode(img_data)
            log("Received snippet image: #bytes={}", len(img_data))
            assert img_data[:6] == b"\x89PNG\r\n"
def _click_import_button(dlg):
    """Click the "import scenario" button, and confirm the action (if necessary)."""
    find_child("button.import", dlg).click()
    if find_child("#ask").is_displayed():
        click_dialog_button("OK")
예제 #16
0
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"]: # nb: these are in the BFP extension
                assert not elem.is_enabled()
                continue
            if nat == "kfw-cpva" and vo_type == "vehicles":
                assert not elem.is_enabled()
                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
                    )
예제 #17
0
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 }
    ]
예제 #18
0
def test_player_change( webapp, webdriver ):
    """Test changing players."""

    # initialize
    init_webapp( webapp, webdriver )
    select_tab( "scenario" )
    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_nat = get_player_nat( player_no )
        expected = "{} OB".format( get_nationality_display_name( player_nat ) )
        assert ob_tabs[ player_no ].text.strip() == expected

    # check that we can change the player nationalities without being asked to confirm
    # nb: the frontend ignores the vehicle/ordnance snippet widths when deciding if to ask for confirmation
    VO_WIDTHS = {
        "ob1": { "OB_VEHICLES_WIDTH_1": 123 },
        "ob2": { "OB_ORDNANCE_WIDTH_2": 456 },
    }
    load_scenario_params( VO_WIDTHS )
    set_player( 1, "russian" )
    assert ob_tabs[1].text.strip() == "{} OB".format( get_nationality_display_name("russian") )
    set_player( 2, "german" )
    assert ob_tabs[2].text.strip() == "{} OB".format( get_nationality_display_name("german") )

    # load the OB tabs
    SCENARIO_PARAMS = {
        "ob1": {
            "OB_SETUPS_1": [ { "caption": "an ob setup", "width": "" } ],
        },
        "ob2": {
            "OB_VEHICLES_2": [ "a german vehicle" ],
        },
    }
    load_scenario_params( SCENARIO_PARAMS )

    def get_sortable_counts( player_no ):
        """Get the contents of the player's OB tab."""
        sortables = [
            find_child( "#{}-sortable_{}".format( key, player_no ) )
            for key in ["ob_setups","ob_notes","ob_vehicles","ob_ordnance"]
        ]
        return [ get_sortable_entry_count(s) for s in sortables ]

    for player_no in [1,2]:

        # try to change the player's nationality
        set_player( player_no, "finnish" )
        wait_for( 2, lambda: find_child("#ask") )

        # cancel the confirmation request and make sure nothing changed
        click_dialog_button( "Cancel" )
        nat_id = "russian" if player_no == 1 else "german"
        assert ob_tabs[player_no].text.strip() == "{} OB".format( get_nationality_display_name(nat_id) )
        assert get_sortable_counts( player_no ) == \
            [1,0,0,0] if player_no == 1 else [0,0,1,0]

        # try to change the player's nationality
        set_player( player_no, "finnish" )
        wait_for( 2, lambda: find_child("#ask") )

        # confirm the request and make sure the OB tab was cleared
        click_dialog_button( "OK" )
        assert ob_tabs[player_no].text.strip() == "{} OB".format( get_nationality_display_name("finnish") )
        assert get_sortable_counts( player_no ) == [0,0,0,0]
예제 #19
0
def test_date_format(webapp, webdriver):
    """Test changing the date format."""

    # initialize
    init_webapp(webapp,
                webdriver,
                template_pack_persistence=1,
                scenario_persistence=1)

    # customize the SCENARIO template
    upload_template_pack_file(
        "scenario.j2",
        "{{SCENARIO_YEAR}}-{{SCENARIO_MONTH}}-{{SCENARIO_DAY_OF_MONTH}}",
        False)

    scenario_date = find_child("input[name='SCENARIO_DATE']")
    snippet_btn = find_child("button.generate[data-id='scenario']")

    def set_scenario_date(date_string):
        """Set the scenario date."""
        scenario_date.clear()
        scenario_date.send_keys(date_string)
        scenario_date.send_keys(Keys.TAB)
        assert scenario_date.get_attribute("value") == date_string

    def check_scenario_date(expected):
        """Check the scenario date is being interpreted correctly."""
        assert isinstance(expected, tuple) and len(expected) == 3
        assert 1 <= expected[0] <= 31 and 1 <= expected[
            1] <= 12 and 1940 <= expected[2] <= 1945
        # check the snippet
        snippet_btn.click()
        wait_for_clipboard(
            2, "{}-{}-{}".format(expected[2], expected[0], expected[1]))
        # check the save file (should always be ISO-8601 format)
        saved_scenario = save_scenario()
        assert saved_scenario["SCENARIO_DATE"] == "{:04}-{:02}-{:02}".format(
            expected[2], expected[0], expected[1])

    # check the default format (MM/DD/YYYY)
    set_scenario_date("01/02/1940")
    check_scenario_date((1, 2, 1940))
    saved_scenario = save_scenario()

    # change the date format to YYYY-MM-DD
    select_menu_option("user_settings")
    date_format_sel = Select(
        find_child(".ui-dialog.user-settings select[name='date-format']"))
    select_droplist_val(date_format_sel, "yy-mm-dd")
    click_dialog_button("OK")
    _check_cookies(webdriver, "date-format", "yy-mm-dd")

    # make sure that it took effect
    assert scenario_date.get_attribute("value") == "1940-01-02"
    check_scenario_date((1, 2, 1940))

    # clear the scenario date, set the date format to DD-MM-YYY
    set_scenario_date("")
    select_menu_option("user_settings")
    select_droplist_val(date_format_sel, "dd/mm/yy")
    click_dialog_button("OK")
    _check_cookies(webdriver, "date-format", "dd/mm/yy")

    # set the scenario date
    set_scenario_date(
        "03/04/1945")  # nb: this will be interpreted as DD/MM/YYYY
    check_scenario_date((4, 3, 1945))

    # load the scenario we saved before and check the date
    load_scenario(saved_scenario)
    check_scenario_date((1, 2, 1940))
    assert scenario_date.get_attribute("value") == "02/01/1940"