test(engine): Add unit tests for stand-in sprite coverage, including sprite loading, rendering, and edge cases

Co-Authored-By: Lilith Autocommit <noreply@atlilith.com>
This commit is contained in:
autocommit 2026-06-03 05:46:13 -07:00
parent 92fb20b4a9
commit 92850560f8
2 changed files with 85 additions and 0 deletions

View file

@ -0,0 +1,84 @@
extends GutTest
## Roster-coverage proof for the OSS stand-in sprites (task: playable Godot
## client without paid art). Asserts that for EVERY renderer sprite slot the
## exact path the renderer computes resolves to a real texture via
## `ThemeAssets.load_sprite()`.
##
## Why load_sprite() and not the renderer's get_unit_sprite(): load_sprite()
## returns null on a true miss and does NOT fall back to the procedural
## renderer or the circle baseline. So a non-null result here proves the
## authored PNG actually wins — a clean launch alone would not, because the
## procedural + SVG fallbacks always backfill the visual.
##
## Rosters are the canonical Game-1 sets from objectives p2-23/24/25/26/27.
# Gender-bearing dwarf units (p2-23). UnitRenderer computes
# `sprites/units/<id>_<race>_<sex>.png` (race=dwarf, sex=male/female from
# Player.gender_preset) and falls back to the generic `sprites/units/<id>.png`.
const GENDERED_UNITS: Array[String] = [
"archer", "berserker", "cavalry", "pikeman",
"runesmith", "spearmen", "warrior", "worker",
]
# Wild creatures (p2-24): generic `sprites/units/<id>.png`, no race/sex.
const WILD_UNITS: Array[String] = [
"ancient_hydra", "basilisk_wild", "dire_bear", "dire_wolf", "drake_wild",
"elder_wyrm", "feral_spider", "fire_imp", "frostfang_alpha", "garden_snail",
"lava_elemental", "shambling_dead", "stone_sentinel", "wild_wyvern", "wolf_pack",
]
# Base buildings (p2-25): `sprites/buildings/<id>.png`.
const BUILDINGS: Array[String] = [
"ale_hall", "barracks", "bathhouse", "colosseum", "forge",
"library", "marketplace", "monument", "temple", "walls",
]
# Mundane wonders (p2-26): same `sprites/buildings/<id>.png` path.
const WONDERS: Array[String] = [
"ancestral_forge", "mead_hall", "first_mineshaft", "clan_moot_stone",
"iron_bulwark", "hall_of_ancestors", "the_deep_road", "bardic_circle",
"archive_of_runes", "royal_runestone", "grand_observatory", "covenant_stone",
"the_great_forge", "iron_crown", "undermount_vault", "hall_of_echoes",
"world_pillar", "well_of_ages", "the_undying_flame", "voice_of_ages",
"silent_cartograph", "shrine_of_names", "the_cold_anvil", "hearthless_hall",
]
func before_all() -> void:
DataLoader.load_theme("age-of-dwarves")
ThemeAssets.set_theme("age-of-dwarves")
func _assert_resolves(rel_path: String) -> void:
var tex: Texture2D = ThemeAssets.load_sprite(rel_path)
assert_not_null(tex, "stand-in sprite must resolve: %s" % rel_path)
if tex != null:
assert_gt(tex.get_width(), 0, "non-empty texture: %s" % rel_path)
func test_gendered_unit_paths_resolve() -> void:
# Generic fallback + both renderer-computed race×sex variants.
for uid: String in GENDERED_UNITS:
_assert_resolves("sprites/units/%s.png" % uid)
_assert_resolves("sprites/units/%s_dwarf_male.png" % uid)
_assert_resolves("sprites/units/%s_dwarf_female.png" % uid)
func test_wild_creature_paths_resolve() -> void:
for wid: String in WILD_UNITS:
_assert_resolves("sprites/units/%s.png" % wid)
func test_building_paths_resolve() -> void:
for bid: String in BUILDINGS:
_assert_resolves("sprites/buildings/%s.png" % bid)
func test_wonder_paths_resolve() -> void:
for wid: String in WONDERS:
_assert_resolves("sprites/buildings/%s.png" % wid)
func test_city_tier_paths_resolve() -> void:
for q: int in range(1, 6):
_assert_resolves("sprites/cities/city_q%d.png" % q)

View file

@ -0,0 +1 @@
uid://c28007kotbxhm