use std::path::{Path, PathBuf}; use game_service::{CardRef, Catalog, DataSelector}; use logic::table; fn assets_root() -> Option { let root = Path::new(env!("CARGO_MANIFEST_DIR")) .join("../../assets") .canonicalize() .ok()?; root.join("csv_logic/spells_characters.csv").is_file().then_some(root) } #[test] fn the_shipped_client_tables_load_and_resolve_by_name() { let Some(root) = assets_root() else { eprintln!("assets/ is absent, skipping the shipped catalog check"); return; }; let catalog = Catalog::load(Some(&root)); assert!(catalog.is_loaded(), "catalog failed to load from {root:?}"); let tables = catalog.tables(); assert_eq!(tables.loaded_files().len(), 44); assert!(tables.skipped_files().is_empty(), "{:?}", tables.skipped_files()); assert_eq!( tables.global_id_by_name(table::ARENAS, "TrainingCamp"), Some(titan::GlobalId::new(table::ARENAS, 0)) ); assert_eq!( tables.global_id_by_name(table::RESOURCES, "Gold"), Some(titan::GlobalId::new(table::RESOURCES, 1)) ); assert_eq!( tables.global_id_by_name(table::RESOURCES, "Diamonds"), Some(titan::GlobalId::new(table::RESOURCES, 0)) ); let knight = tables.spell_by_name("Knight").expect("Knight"); assert_eq!(knight.global_id().class_id, table::SPELLS_CHARACTERS); assert_eq!(knight.global_id().instance_id, 0); let fireball = tables.spell_by_name("Fireball").expect("Fireball"); assert_eq!(fireball.global_id().class_id, table::SPELLS_OTHER); let cannon = tables.spell_by_name("Cannon").expect("Cannon"); assert_eq!(cannon.global_id().class_id, table::SPELLS_BUILDINGS); } #[test] fn continuation_rows_build_the_per_level_arrays() { let Some(root) = assets_root() else { return; }; let catalog = Catalog::load(Some(&root)); let tables = catalog.tables(); let common = tables .data_by_name(table::RARITIES, "Common") .expect("Common rarity"); assert!( common.array_size() > 1, "rarities.csv uses continuation rows for the upgrade curve" ); assert_eq!(common.int_at("UpgradeCost", 0), 5); assert_eq!(common.int_at("UpgradeCost", 1), 20); assert_eq!(common.int("LevelCount"), 12); assert_eq!( common.int_at("UpgradeCost", 999), common.int_at("UpgradeCost", common.array_size() - 1), "reading past the end clamps to the last level" ); let newbie = tables .treasure_chest_by_name("Newbie1") .expect("Newbie1 chest"); assert_eq!(newbie.string("Arena"), "TrainingCamp"); let row = newbie.row().expect("row"); let guaranteed = newbie .csv_table() .column_index("GuaranteedSpells") .expect("column"); assert_eq!(row.value_count(guaranteed), 2); assert_eq!(row.string_at(guaranteed, 0), "Knight"); assert_eq!(row.string_at(guaranteed, 1), "Arrows"); } #[test] fn the_default_starter_profile_resolves_against_the_real_tables() { let Some(root) = assets_root() else { return; }; let catalog = Catalog::load(Some(&root)); let starter = game_service::StarterProfile::default(); for card in starter.deck.iter().chain(starter.extra_collection.iter()) { assert!( catalog.resolve_card(card).is_some(), "starter card {card:?} does not resolve" ); } let gold = catalog.resolve_resource(&DataSelector::named("Gold")); assert_eq!(gold.name(), "Gold"); assert_eq!( gold.global_id(), Some(titan::GlobalId::new(table::RESOURCES, 1)) ); let arena = catalog.resolve_arena(&starter.arena); assert_eq!(arena.table_index(), Some(table::ARENAS)); assert!(catalog.resolve_card(&CardRef::named("NotACard")).is_none()); }