test(engine): add missing coverage for settings and animation plugins

settings_plugin: tests for cycle_unlocked (wrap, advance, single-element,
unknown-current, empty), volume floor clamping, and O-key screen toggle.

animation_plugin: tests for anim_speed_to_secs mapping (Fast < Normal,
Instant = 0), toast auto-dismiss on expired timer, toast survival when
timer positive, InfoToastEvent spawning a ToastOverlay, and
SettingsChangedEvent updating EffectiveSlideDuration.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
root
2026-04-27 04:37:32 +00:00
parent de01566e47
commit c06458cf80
2 changed files with 136 additions and 0 deletions
+60
View File
@@ -882,4 +882,64 @@ mod tests {
let mut cursor = events.get_cursor();
assert_eq!(cursor.read(events).count(), 0);
}
#[test]
fn volume_clamped_at_zero_does_not_emit_event() {
let mut app = headless_app();
app.world_mut().resource_mut::<SettingsResource>().0.sfx_volume = 0.0;
press(&mut app, KeyCode::BracketLeft);
app.update();
let after = app.world().resource::<SettingsResource>().0.sfx_volume;
assert!(after >= 0.0, "volume must not go below zero");
let events = app.world().resource::<Events<SettingsChangedEvent>>();
let mut cursor = events.get_cursor();
assert_eq!(cursor.read(events).count(), 0, "no event when clamped at floor");
}
#[test]
fn pressing_o_toggles_settings_screen_flag() {
let mut app = headless_app();
assert!(!app.world().resource::<SettingsScreen>().0, "screen is closed initially");
press(&mut app, KeyCode::KeyO);
app.update();
assert!(app.world().resource::<SettingsScreen>().0, "O opens settings");
press(&mut app, KeyCode::KeyO);
app.update();
assert!(!app.world().resource::<SettingsScreen>().0, "second O closes settings");
}
// cycle_unlocked pure-function tests
#[test]
fn cycle_unlocked_wraps_at_end() {
// [0, 1, 2] → cycling from 2 wraps to 0
assert_eq!(cycle_unlocked(&[0, 1, 2], 2), 0);
}
#[test]
fn cycle_unlocked_advances_normally() {
assert_eq!(cycle_unlocked(&[0, 1, 2], 0), 1);
assert_eq!(cycle_unlocked(&[0, 1, 2], 1), 2);
}
#[test]
fn cycle_unlocked_single_element_stays() {
// Only one unlockable — cycling always returns it.
assert_eq!(cycle_unlocked(&[0], 0), 0);
}
#[test]
fn cycle_unlocked_current_not_in_list_falls_back_to_second() {
// current=5 is not in [0,1,2]; falls back to pos=0, so next = unlocked[1] = 1
assert_eq!(cycle_unlocked(&[0, 1, 2], 5), 1);
}
#[test]
fn cycle_unlocked_empty_returns_zero() {
assert_eq!(cycle_unlocked(&[], 0), 0);
}
}