def save_scenario(): """Save the scenario.""" marker = set_stored_msg_marker("_scenario-persistence_") select_menu_option("save_scenario") wait_for(2, lambda: get_stored_msg("_scenario-persistence_") != marker) data = get_stored_msg("_scenario-persistence_") return json.loads(data)
def test_zip_files(webapp, webdriver): """Test loading ZIP'ed template packs.""" # initialize webapp.control_tests.set_vo_notes_dir("{TEST}") init_webapp(webapp, webdriver, template_pack_persistence=1) set_player(1, "german") set_player(2, "russian") # upload a template pack that contains a full set of templates zip_data = make_zip_from_files("full") _, marker = upload_template_pack_zip(zip_data, False) assert get_stored_msg("_last-error_") == marker # check that the uploaded templates are being used _check_snippets(webdriver, lambda tid: "Customized {}.".format(tid.upper())) # upload only part of template pack _ = upload_template_pack_zip(zip_data[:int(len(zip_data) / 2)], True) assert get_stored_msg("_last-error_").startswith("Can't unpack the ZIP:") # try uploading an empty template pack _ = upload_template_pack_zip(b"", True) assert get_stored_msg("_last-error_").startswith("Can't unpack the ZIP:")
def test_individual_files(webapp, webdriver): """Test loading individual template files.""" # initialize webapp.control_tests.set_vo_notes_dir("{TEST}") init_webapp(webapp, webdriver, template_pack_persistence=1) set_player(1, "german") set_player(2, "russian") # try uploading a customized version of each template def test_template(template_id, orig_template_id): """Test uploading a customized version of the template.""" # upload a new template _ = upload_template_pack_file(template_id + ".j2", "UPLOADED TEMPLATE", False) # make sure generating a snippet returns the new version _ = _generate_snippet(webdriver, template_id, orig_template_id) wait_for_clipboard(2, "UPLOADED TEMPLATE") for_each_template(test_template) # try uploading a template with an incorrect filename extension _ = upload_template_pack_file("filename.xyz", "UPLOADED TEMPLATE", True) assert "Invalid template extension" in get_stored_msg("_last-error_") # try uploading a template with an unknown filename _ = upload_template_pack_file("unknown.j2", "UPLOADED TEMPLATE", True) assert "Invalid template filename" in get_stored_msg("_last-error_")
def do_test(): #pylint: disable=missing-docstring # initialize init_webapp(webapp, webdriver, vlog_persistence=1, lfa_persistence=1) # analyze the log file _analyze_vlogs("custom-labels.vlog") # download the data marker = set_stored_msg_marker("_lfa-download_") find_child("#lfa button.download").click() wait_for(2, lambda: get_stored_msg("_lfa-download_") != marker) data = get_stored_msg("_lfa-download_") # check the results data = data.split("\n") rows = list(csv.reader(data, quoting=csv.QUOTE_NONNUMERIC)) assert rows == [[ "Log file", "Phase", "Player", "Type", "Die 1", "Die 2" ], ["custom-labels.vlog", "", "test", "Other", 5, 3], ["", "", "test", "Other", 3, ""], ["", "Custom Label 1", "test", "Other", 6, 6], ["", "", "test", "RS", 6, ""], ["", "Axis 1 PFPh", "test", "Other", 4, 4], ["", "", "test", "RS", 6, ""], ["", "Custom label 2", "test", "Other", 2, 1], ["", "", "test", "RS", 1, ""]]
def do_test(): #pylint: disable=missing-docstring # initialize init_webapp(webapp, webdriver, vlog_persistence=1, lfa_persistence=1) # analyze the log file _analyze_vlogs("download-test.vlog") # download the data marker = set_stored_msg_marker("_lfa-download_") find_child("#lfa button.download").click() wait_for(2, lambda: get_stored_msg("_lfa-download_") != marker) data = get_stored_msg("_lfa-download_") # check the results data = data.split("\n") rows = list(csv.reader(data, quoting=csv.QUOTE_NONNUMERIC)) assert rows == [[ "Log file", "Phase", "Player", "Type", "Die 1", "Die 2" ], ["download-test.vlog", "", 'Joey "The Lips" Blow', "IFT", 4, 1], ["", "", 'Joey "The Lips" Blow', "IFT", 2, 5], ["", "", 'Joey "The Lips" Blow', "RS", 2, ""], ["", "UN 1 PFPh", "\u65e5\u672c Guy", "IFT", 4, 6], ["", "", "\u65e5\u672c Guy", "IFT", 2, 6], ["", "", "\u65e5\u672c Guy", "RS", 3, ""], ["", "UN 1 MPh", 'Joey "The Lips" Blow', "IFT", 2, 6], ["", "", 'Joey "The Lips" Blow', "IFT", 2, 3], ["", "", 'Joey "The Lips" Blow', "RS", 3, ""]]
def _test_snippet(btn, params, expected, expected2): """Do a single test.""" # set the template parameters and generate the snippet set_template_params(params) marker = set_stored_msg_marker("_last-warning_") btn.click() def reformat(clipboard): #pylint: disable=missing-docstring lines = [l.strip() for l in clipboard.split("\n")] return " | ".join(l for l in lines if l) wait_for_clipboard(2, expected, transform=reformat) # check warnings for mandatory parameters last_warning = get_stored_msg("_last-warning_") 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 last_warning == marker
def do_check_snippets( btn, date, expected, warning ): """Check that snippets are being generated correctly.""" # change the scenario date, check that the button is displayed correctly set_scenario_date( "{:02}/01/{:04}".format( date[1], date[0] ) ) select_tab( "ob1" ) classes = btn.get_attribute( "class" ) classes = classes.split() if classes else [] if warning: assert "inactive" in classes else: assert "inactive" not in classes # test snippet generation marker = set_stored_msg_marker( "_last-warning_" ) btn.click() wait_for_clipboard( 2, expected ) # check if a warning was issued last_warning = get_stored_msg( "_last-warning_" ) if warning: assert "are only available" in last_warning expected_image_url = "snippet-disabled.png" else: assert last_warning == marker expected_image_url = "snippet.png" wait_for( 2, lambda: expected_image_url in find_child( "img", btn ).get_attribute( "src" ) )
def test_nationality_data(webapp, webdriver): """Test a template pack with nationality data.""" # initialize init_webapp(webapp, webdriver, template_pack_persistence=1) # select the British as player 1 player1_sel = set_player(1, "british") tab_ob1 = find_child("a[href='#tabs-ob1']") assert tab_ob1.text.strip() == "British OB" # FUDGE! player1_sel.first_selected_option.text doesn't contain the right value # if we're using jQuery selectmenu's :-/ assert get_player_nat(1) == "british" droplist_vals = get_droplist_vals_index(player1_sel) assert droplist_vals["british"] == "British" # upload a template pack that contains nationality data zip_data = make_zip_from_files("with-nationality-data") _, marker = upload_template_pack_zip(zip_data, False) assert get_stored_msg("_last-error_") == marker # check that the UI was updated correctly assert tab_ob1.text.strip() == "Poms! OB" assert get_player_nat(1) == "british" droplist_vals2 = get_droplist_vals_index(player1_sel) assert droplist_vals2["british"] == "Poms!" # check that there is a new Korean player del droplist_vals2["korean"] droplist_vals2 = { k: "British" if v == "Poms!" else v for k, v in droplist_vals2.items() } assert droplist_vals2 == droplist_vals
def _analyze_vlogs(fnames): """Analyze log file(s).""" # initialize if isinstance(fnames, str): fnames = [fnames] select_menu_option("analyze_vlog") dlg = wait_for_elem(2, ".ui-dialog.lfa-upload") # add each log file for fno, fname in enumerate(fnames): fname = os.path.join( os.path.split(__file__)[0], "fixtures/analyze-vlog/" + fname) with open(fname, "rb") as fp: vlog_data = fp.read() set_stored_msg( "_vlog-persistence_", "{}|{}".format( os.path.split(fname)[1], base64.b64encode(vlog_data).decode("utf-8"))) find_child("#lfa-upload .{}".format("hint" if fno == 0 else "files"), dlg).click() wait_for(2, lambda: get_stored_msg("_vlog-persistence_") == "") # start the analysis find_child("button.ok", dlg).click() wait_for_elem(30, "#lfa")
def load_scenario(scenario, webdriver=None): """Load a scenario into the UI.""" set_stored_msg("_scenario-persistence_", json.dumps(scenario), webdriver) _ = set_stored_msg_marker("_last-info_", webdriver) select_menu_option("load_scenario", webdriver) wait_for( 2, lambda: get_stored_msg("_last-info_", webdriver) == "The scenario was loaded.")
def _update_vsav(fname, expected): """Update a VASL scenario.""" # read the VSAV data with open(fname, "rb") as fp: vsav_data = fp.read() # send the VSAV data to the front-end to be updated set_stored_msg("_vsav-persistence_", base64.b64encode(vsav_data).decode("utf-8")) _ = set_stored_msg_marker("_last-info_") _ = set_stored_msg_marker("_last-warning_") select_menu_option("update_vsav") # wait for the front-end to receive the data def check_response(): # NOTE: If something is misconfigured, the error response can get stored in the persistence buffer # really quickly i.e. before we get a chance to detect it here being cleared first. resp = get_stored_msg("_vsav-persistence_") return resp == "" or resp.startswith("ERROR:") wait_for(2, check_response) # wait for the updated data to come back timeout = 120 if os.name == "nt" else 60 wait_for(timeout, lambda: get_stored_msg("_vsav-persistence_") != "") updated_vsav_data = get_stored_msg("_vsav-persistence_") if updated_vsav_data.startswith("ERROR: "): raise RuntimeError(updated_vsav_data) updated_vsav_data = base64.b64decode(updated_vsav_data) # parse the VASSAL shim report if expected: report = {} msg = get_stored_msg("_last-warning_" if "deleted" in expected else "_last-info_") assert "The VASL scenario was updated:" in msg for mo2 in re.finditer("<li>([^<]+)", msg): mo3 = re.search(r"^(\d+) labels? (were|was) ([a-z]+)", mo2.group(1)) report[mo3.group(3)] = int(mo3.group(1)) assert report == expected else: assert "No changes were made" in get_stored_msg("_last-info_") return updated_vsav_data
def _do_upload_template_pack(data, error_expected): """Upload a template pack.""" # upload the template pack set_stored_msg("_template-pack-persistence_", data) info_marker = set_stored_msg_marker("_last-info_") error_marker = set_stored_msg_marker("_last-error_") select_menu_option("template_pack") # wait for the front-end to finish if error_expected: func = lambda: get_stored_msg("_last-error_") != error_marker else: func = lambda: "was loaded" in get_stored_msg("_last-info_") wait_for(2, func) return info_marker, error_marker
def analyze_vsav(fname, expected_ob1, expected_ob2, expected_report): """Analyze a VASL scenario.""" # read the VSAV data fname = os.path.join( os.path.split(__file__)[0], "fixtures/analyze-vsav/" + fname) with open(fname, "rb") as fp: vsav_data = fp.read() # send the VSAV data to the front-end to be analyzed set_stored_msg("_vsav-persistence_", base64.b64encode(vsav_data).decode("utf-8")) prev_info_msg = set_stored_msg_marker("_last-info_") set_stored_msg_marker("_last-warning_") select_menu_option("analyze_vsav") # wait for the analysis to finish wait_for(2, lambda: find_child("#please-wait").is_displayed()) wait_for(60, lambda: not find_child("#please-wait").is_displayed()) # check the results saved_scenario = save_scenario() def get_ids(key): #pylint: disable=missing-docstring return set( (v["id"], v.get("image_id")) for v in saved_scenario.get(key, [])) def adjust_expected(vals): #pylint: disable=missing-docstring return set(v if isinstance(v, tuple) else (v, None) for v in vals) assert get_ids("OB_VEHICLES_1") == adjust_expected(expected_ob1[0]) assert get_ids("OB_ORDNANCE_1") == adjust_expected(expected_ob1[1]) assert get_ids("OB_VEHICLES_2") == adjust_expected(expected_ob2[0]) assert get_ids("OB_ORDNANCE_2") == adjust_expected(expected_ob2[1]) # check the report msg = get_stored_msg("_last-info_") if msg == prev_info_msg: msg = get_stored_msg("_last-warning_") assert all(e in msg for e in expected_report)
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)
def test_unknown_vo(webapp, webdriver): """Test detection of unknown vehicles/ordnance.""" # initialize init_webapp(webapp, webdriver, scenario_persistence=1) # load a scenario that has unknown vehicles/ordnance SCENARIO_PARAMS = { "PLAYER_1": "german", "OB_VEHICLES_1": [ { "name": "unknown vehicle 1a" }, { "name": "unknown vehicle 1b" }, ], "OB_ORDNANCE_1": [ { "name": "unknown ordnance 1a" }, { "name": "unknown ordnance 1b" }, ], "PLAYER_2": "russian", "OB_VEHICLES_2": [{ "name": "unknown vehicle 2" }], "OB_ORDNANCE_2": [{ "name": "unknown ordnance 2" }], } _ = set_stored_msg_marker("_last-warning_") load_scenario(SCENARIO_PARAMS) last_warning = get_stored_msg("_last-warning_") assert last_warning.startswith("Unknown vehicles/ordnance:") for key, vals in SCENARIO_PARAMS.items(): if not key.startswith(("OB_VEHICLES_", "OB_ORDNANCE_")): continue assert all(v["name"] in last_warning for v in vals)
def test_invalid_vo_image_ids( webapp, webdriver ): """Test loading scenarios that contain invalid V/O image ID's.""" # initialize init_webapp( webapp, webdriver, scenario_persistence=1 ) # test each save file dname = os.path.join( os.path.split(__file__)[0], "fixtures/invalid-vo-image-ids" ) for root,_,fnames in os.walk(dname): for fname in fnames: fname = os.path.join( root, fname ) if os.path.splitext( fname )[1] != ".json": continue # load the next scenario, make sure a warning was issued for the V/O image ID with open( fname, "r", encoding="utf-8" ) as fp: data = json.load( fp ) set_stored_msg_marker( "_last-warning_" ) load_scenario( data ) last_warning = get_stored_msg( "_last-warning_" ) assert "Invalid V/O image ID" in last_warning
def check_response(): # NOTE: If something is misconfigured, the error response can get stored in the persistence buffer # really quickly i.e. before we get a chance to detect it here being cleared first. resp = get_stored_msg("_vsav-persistence_") return resp == "" or resp.startswith("ERROR:")
def update_vsav_thread(webapp_url, vsav_fname, vsav_data): """Test updating VASL scenario files.""" # initialize vsav_data_b64 = base64.b64encode(vsav_data).decode("utf-8") with WebDriver() as webdriver: # initialize webdriver = webdriver.driver init_webapp(webdriver, webapp_url, ["vsav_persistence", "scenario_persistence"]) # load a test scenario fname = os.path.join( os.path.split(__file__)[0], "../webapp/tests/fixtures/update-vsav/full.json") with open(fname, "r", encoding="utf-8") as fp: saved_scenario = json.load(fp) load_scenario(saved_scenario, webdriver) while not shutdown_event.is_set(): try: # send the VSAV data to the front-end to be updated log("Updating VSAV: {}", vsav_fname) set_stored_msg("_vsav-persistence_", vsav_data_b64, webdriver) select_menu_option("update_vsav", webdriver) start_time = time.time() # wait for the front-end to receive the data wait_for( 2 * thread_count, lambda: get_stored_msg( "_vsav-persistence_", webdriver) == "") # wait for the updated data to arrive wait_for( 60 * thread_count, lambda: get_stored_msg( "_vsav-persistence_", webdriver) != "") elapsed_time = time.time() - start_time # get the updated VSAV data updated_vsav_data = get_stored_msg("_vsav-persistence_", webdriver) if updated_vsav_data.startswith("ERROR: "): raise RuntimeError(updated_vsav_data) updated_vsav_data = base64.b64decode(updated_vsav_data) # check the updated VSAV log("Received updated VSAV data: #bytes={}", len(updated_vsav_data)) assert updated_vsav_data[:2] == b"PK" # update the stats with stats_lock: stats["update vsav"][0] += 1 stats["update vsav"][1] += elapsed_time except (ConnectionRefusedError, ConnectionResetError, http.client.RemoteDisconnected): if shutdown_event.is_set(): break raise
def test_scenario_persistence(webapp, webdriver): #pylint: disable=too-many-statements,too-many-locals,too-many-branches """Test loading/saving scenarios.""" # initialize init_webapp(webapp, webdriver, scenario_persistence=1) def check_ob_tabs(*args): """Check that the OB tabs have been set correctly.""" for player_no in [1, 2]: elem = find_child( "#tabs .ui-tabs-nav a[href='#tabs-ob{}']".format(player_no)) nat = args[player_no - 1] assert elem.text.strip() == "{} OB".format( get_nationality_display_name(nat)) def check_window_title(expected): """Check the window title.""" if expected: expected = "{} - {}".format(APP_NAME, expected) else: expected = APP_NAME assert webdriver.title == expected # load the scenario fields SCENARIO_PARAMS = { "scenario": { "SCENARIO_NAME": "my test scenario", "SCENARIO_ID": "xyz123", "SCENARIO_LOCATION": "right here", "SCENARIO_THEATER": "PTO", "SCENARIO_DATE": "12/31/1945", "SCENARIO_WIDTH": "101", "ASA_ID": "", "ROAR_ID": "", "PLAYER_1": "russian", "PLAYER_1_ELR": "1", "PLAYER_1_SAN": "2", "PLAYER_1_DESCRIPTION": "The Army of Player 1", "PLAYER_2": "german", "PLAYER_2_ELR": "3", "PLAYER_2_SAN": "4", "PLAYER_2_DESCRIPTION": "The Army of Player 2", "PLAYERS_WIDTH": "42", "VICTORY_CONDITIONS": "just do it!", "VICTORY_CONDITIONS_WIDTH": "102", "SCENARIO_NOTES": [{ "caption": "note #1", "width": "" }, { "caption": "note #2", "width": "100px" }], "SSR": ["This is an SSR.", "This is another SSR."], "SSR_WIDTH": "103", }, "ob1": { "OB_SETUPS_1": [{ "caption": "ob setup 1a", "width": "" }, { "caption": "ob setup 1b", "width": "200px" }], "OB_NOTES_1": [{ "caption": "ob note 1a", "width": "10em" }, { "caption": "ob note 1b", "width": "" }], "OB_VEHICLES_1": ["a russian vehicle", "another russian vehicle"], "OB_VEHICLES_WIDTH_1": "202", "OB_VEHICLES_MA_NOTES_WIDTH_1": "203", "OB_ORDNANCE_1": ["a russian ordnance", "another russian ordnance"], "OB_ORDNANCE_WIDTH_1": "204", "OB_ORDNANCE_MA_NOTES_WIDTH_1": "205", }, "ob2": { "OB_SETUPS_2": [{ "caption": "ob setup 2", "width": "" }], "OB_NOTES_2": [{ "caption": "ob note 2", "width": "" }], "OB_VEHICLES_2": ["a german vehicle"], "OB_VEHICLES_WIDTH_2": "302", "OB_VEHICLES_MA_NOTES_WIDTH_2": "303", "OB_ORDNANCE_2": ["a german ordnance"], "OB_ORDNANCE_WIDTH_2": "304", "OB_ORDNANCE_MA_NOTES_WIDTH_2": "305", }, } load_scenario_params(SCENARIO_PARAMS) check_window_title("my test scenario (xyz123) (*)") check_ob_tabs("russian", "german") assert_scenario_params_complete(SCENARIO_PARAMS, True) # save the scenario and check the results saved_scenario = save_scenario() assert saved_scenario["_app_version"] == APP_VERSION scenario_creation_time = saved_scenario["_creation_time"] assert saved_scenario["_last_update_time"] == scenario_creation_time expected = { k: v for tab in SCENARIO_PARAMS.values() for k, v in tab.items() } mo = re.search(r"^(\d{2})/(\d{2})/(\d{4})$", expected["SCENARIO_DATE"]) expected["SCENARIO_DATE"] = "{}-{}-{}".format( mo.group(3), mo.group(1), mo.group(2)) # nb: convert from ISO-8601 saved_scenario2 = { k: v for k, v in saved_scenario.items() if not k.startswith("_") } for key in saved_scenario2: if re.search(r"^OB_(VEHICLES|ORDNANCE)_\d$", key): for vo_entry in saved_scenario2[key]: del vo_entry["id"] for key in expected: if re.search(r"^OB_(VEHICLES|ORDNANCE)_\d$", key): expected[key] = [{"name": name} for name in expected[key]] for player_no in (1, 2): for vo_type in ("OB_SETUPS", "OB_NOTES"): entries = expected["{}_{}".format(vo_type, player_no)] for i, entry in enumerate(entries): entry["id"] = 1 + i for vo_type in ("OB_VEHICLES", "OB_ORDNANCE"): entries = expected["{}_{}".format(vo_type, player_no)] for i, entry in enumerate(entries): entry["seq_id"] = 1 + i for i, entry in enumerate(expected["SCENARIO_NOTES"]): entry["id"] = 1 + i assert saved_scenario2 == expected # make sure that our list of scenario parameters is correct lhs = set(saved_scenario2.keys()) rhs = set(itertools.chain(*ALL_SCENARIO_PARAMS.values())) assert lhs == rhs # reset the scenario and check the save results _ = set_stored_msg_marker("_last-info_") select_menu_option("new_scenario") wait_for( 2, lambda: get_stored_msg("_last-info_") == "The scenario was reset.") check_window_title("") check_ob_tabs("german", "russian") data = save_scenario() assert data["_app_version"] == APP_VERSION assert data["_last_update_time"] == data["_creation_time"] assert data["_creation_time"] > scenario_creation_time data2 = {k: v for k, v in data.items() if not k.startswith("_") and v} assert data2 == { "SCENARIO_THEATER": "ETO", "PLAYER_1": "german", "OB_VEHICLES_MA_NOTES_WIDTH_1": "300px", "OB_ORDNANCE_MA_NOTES_WIDTH_1": "300px", "PLAYER_2": "russian", "OB_VEHICLES_MA_NOTES_WIDTH_2": "300px", "OB_ORDNANCE_MA_NOTES_WIDTH_2": "300px", } # 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("#ob_vehicles-sortable_1"), find_child( "#ob_ordnance-sortable_1") vehicles2, ordnance2 = find_child("#ob_vehicles-sortable_2"), find_child( "#ob_ordnance-sortable_2") elems = { c.get_attribute("name"): c for elem_type in ("input", "textarea", "select") for c in find_children(elem_type) } # load a scenario and make sure it was loaded into the UI correctly load_scenario(saved_scenario) check_window_title("my test scenario (xyz123)") check_ob_tabs("russian", "german") for tab_id, params in SCENARIO_PARAMS.items(): select_tab(tab_id) for field, val in params.items(): 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 ("OB_VEHICLES_1", "OB_ORDNANCE_1", "OB_VEHICLES_2", "OB_ORDNANCE_2"): 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: assert elem.get_attribute("value") == val 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"] ] 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"] ] # NOTE: We deleted the "id" fields above, so we rely on the legacy handling of loading by name :-/ assert get_sortable_vo_names( vehicles1) == SCENARIO_PARAMS["ob1"]["OB_VEHICLES_1"] assert get_sortable_vo_names( ordnance1) == SCENARIO_PARAMS["ob1"]["OB_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_vo_names( vehicles2) == SCENARIO_PARAMS["ob2"]["OB_VEHICLES_2"] assert get_sortable_vo_names( ordnance2) == SCENARIO_PARAMS["ob2"]["OB_ORDNANCE_2"] # save the scenario, make sure the timestamps are correct data = save_scenario() assert data["_creation_time"] == scenario_creation_time assert data["_last_update_time"] > scenario_creation_time