1static FORCED: std::sync::OnceLock<bool> = std::sync::OnceLock::new();
9
10pub(crate) fn forced_reduce_motion() -> bool {
15 *FORCED.get_or_init(|| {
16 let on = |key: &str| std::env::var(key).as_deref() == Ok("1");
17 on("DAY_TEST_FAST") || on("DAY_REDUCE_MOTION")
18 })
19}
20
21pub fn fast_animations() -> bool {
25 crate::reduce_motion_now()
26}
27
28#[cfg(target_arch = "wasm32")]
30pub fn init_fast_animations(enabled: bool) {
31 let _ = FORCED.set(enabled);
32}
33
34#[cfg(test)]
35mod tests {
36 use crate::frame::{FrameClock, install_frame_requester};
37 use crate::tween::{Timing, Tweened, animate};
38 use day_spec::{AnimSpec, FrameStamp};
39 use std::{cell::RefCell, collections::VecDeque, rc::Rc};
40
41 #[test]
42 fn fast_motion_preserves_endpoints_and_continuous_clocks() {
43 if std::env::var_os("DAY_MOTION_TEST_CHILD").is_none() {
46 for fast in ["0", "1"] {
47 assert!(
48 std::process::Command::new(std::env::current_exe().unwrap())
49 .args([
50 "--exact",
51 "testing::tests::fast_motion_preserves_endpoints_and_continuous_clocks"
52 ])
53 .env("DAY_MOTION_TEST_CHILD", "1")
54 .env("DAY_TEST_FAST", fast)
55 .status()
56 .unwrap()
57 .success()
58 );
59 }
60 return;
61 }
62 let fast = super::fast_animations();
63 let pending = Rc::new(RefCell::new(VecDeque::new()));
64 let q = pending.clone();
65 install_frame_requester(move |_, cb| {
66 q.borrow_mut().push_back(cb);
67 Box::new(|| {})
68 });
69 let clock = FrameClock::for_root(crate::RNode::default());
70 let tween = Tweened::on(clock, 0.0);
71 tween.animate_to(42.0, AnimSpec::linear(1000));
72 assert_eq!(tween.get_untracked(), if fast { 42.0 } else { 0.0 });
73 let samples = Rc::new(RefCell::new(Vec::new()));
74 let s = samples.clone();
75 let finite = animate(
76 clock,
77 Timing::new(AnimSpec {
78 repeat: 1,
79 autoreverse: true,
80 delay_ms: 500,
81 ..AnimSpec::linear(1000)
82 }),
83 move |sample| s.borrow_mut().push(sample),
84 );
85 let continuous = clock.subscribe(|_| std::ops::ControlFlow::Continue(()));
86 let forever = animate(
87 clock,
88 Timing::new(AnimSpec {
89 repeat: u32::MAX,
90 ..AnimSpec::linear(1000)
91 }),
92 |sample| assert!(!sample.done),
93 );
94 let instant = Rc::new(RefCell::new(None));
95 let i = instant.clone();
96 let _instant = animate(
97 clock,
98 Timing::new(AnimSpec {
99 repeat: 1,
100 autoreverse: true,
101 ..AnimSpec::linear(0)
102 }),
103 move |sample| *i.borrow_mut() = Some(sample),
104 );
105 let cb = pending.borrow_mut().pop_front().unwrap();
106 cb(FrameStamp::new(1.0));
107 assert_eq!(samples.borrow()[0].done, fast);
108 assert_eq!(samples.borrow()[0].progress, 0.0); assert_eq!(finite.is_active(), !fast);
110 assert!(continuous.is_active() && forever.is_active());
111 let instant = instant.borrow().unwrap();
112 assert!(instant.done);
113 assert_eq!(instant.progress, 1.0); }
115}