Cover the last batch of tickets with tests

The previous ten tickets shipped with almost no coverage - only #109, #113,
#115 and #117 touched a test. That was a gap, not a decision: everything
before it had its behaviour pinned, and #116 in particular added a whole
subsystem nothing was watching.

Four new files and one extended case:

  test_spacial_workshop        #116 - the repair economy end to end: the
                               cost of a repair scales with the damage, the
                               workshop asks logistics for that ore and
                               stops at its buffer, a drone spends when it
                               LEAVES so two cannot double-charge one wall,
                               and a target levelled in flight sends its
                               load home rather than swallowing it
  test_desktop_controls        #118/#121 - both driven through the real
                               routing, because the routing is what was
                               missing; a test calling handle_mouse_button()
                               itself would have passed against both reports
  test_enemy_bomber            #114 - it flies, it faces where it flies, its
                               bombs arrive, and it bombs structures with no
                               fleet in sight
  test_menu_polish             #111/#112/#119/#120 - what each panel shows
  test_wave_system (case G)    #110 - the dev button, and that it does not
                               exist outside dev mode

One assertion worth recording: the craft caption is checked as an EXACT
match against the vessel's display name rather than by hunting for resource
words in it. The first version failed on "Gas Bomber" - a vessel named after
a resource, and always will be. What #111 removed was the price spelled out
underneath, not the name.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Loïc Wisniewski 2026-08-24 12:10:31 +02:00
commit ec7a8f1f17
8 changed files with 790 additions and 0 deletions

View file

@ -25,6 +25,8 @@ extends SceneTree
# E. a launched wave really arrives, around the fleet, and clearing it
# returns the world to peace
# F. the alert is up during the warning and at no other time
# G. #110 - a dev-mode button puts a wave on the board now, skipping both
# the peace and the warning, and it does not exist outside dev mode
var game_state: Node
var scene: Node
@ -222,6 +224,35 @@ func _process(delta: float) -> bool:
return _fail("killing the whole wave did not bring the quiet back")
print("the wave died and the quiet came back")
# --- G. the dev button ---------------------------------------
var dev_button: Control = scene.get_node("UI/DevWaveButton")
game_state.dev_mode = false
dev_button._process(0.0)
if dev_button.visible:
return _fail("the dev wave button is offered in a normal game")
game_state.dev_mode = true
dev_button._process(0.0)
if not dev_button.visible:
return _fail("the dev wave button is hidden in dev mode")
var number_before: int = game_state.wave_number
dev_button.button.pressed.emit()
if game_state.wave_phase != GameState.WAVE_PHASE_ACTIVE:
return _fail("the button left the wave in \"%s\"" % game_state.wave_phase)
if not game_state.wave_pending:
return _fail("the button turned the wave active without owing it to anyone")
if game_state.wave_number != number_before + 1:
return _fail("the forced wave was not counted")
# The point of the button is to SEE the wave, so it skips the
# nine-second alert as well as the fifty-second peace.
if game_state.wave_is_incoming():
return _fail("the button stopped at the warning - that is not \"now\"")
spawner._process(0.0)
if _enemy_count() <= 0:
return _fail("the forced wave produced no enemies")
print("dev button: wave %d on the board at once, %d enemies" \
% [game_state.wave_number, _enemy_count()])
game_state.dev_mode = false
print("TEST_WAVE_SYSTEM: PASS")
quit(0)
return true