Change `Harness::run` to run until no more repaints are requested (#5580)
Previously, `Harness::run` just called `Harness::step` 3 times. If that wasn't enough, tests would often call run multiple times so all animations would finish properly. Also, I introduced `HarnessBuilder::with_step_dt` to customize with how big of a dt each frame is called. I set the default to 1.0 / 6.0 (~6fps) so we don't waste cpu in tests waiting on animations. `HarnessBuilder::max_steps` allows us to control how many steps `Harness::run` should run before panicing. The default is 6, so we run for up to 1.0 logical seconds (six frames at 6 fps), which should be enough to finish most animations. Turns out a lot of snapshots where rendered before fully shown and had a light opacity, those are now fixed. * [x] I have followed the instructions in the PR template
This commit is contained in:
parent
35860418ac
commit
52060c0c41
|
|
@ -775,7 +775,7 @@ impl Context {
|
|||
writer(&mut self.0.write())
|
||||
}
|
||||
|
||||
/// Run the ui code for one 1.
|
||||
/// Run the ui code for one frame.
|
||||
///
|
||||
/// At most [`Options::max_passes`] calls will be issued to `run_ui`,
|
||||
/// and only on the rare occasion that [`Context::request_discard`] is called.
|
||||
|
|
|
|||
|
|
@ -49,7 +49,7 @@ fn test_demo_app() {
|
|||
// Load a local image where we know it exists and loads quickly
|
||||
#[cfg(feature = "image_viewer")]
|
||||
Anchor::ImageViewer => {
|
||||
harness.run();
|
||||
harness.step();
|
||||
|
||||
harness
|
||||
.get_by_role_and_label(Role::TextInput, "URI:")
|
||||
|
|
@ -65,7 +65,8 @@ fn test_demo_app() {
|
|||
_ => {}
|
||||
}
|
||||
|
||||
harness.run();
|
||||
// Can't use Harness::run because fractal clock keeps requesting repaints
|
||||
harness.run_steps(2);
|
||||
|
||||
if let Err(e) = harness.try_snapshot(&anchor.to_string()) {
|
||||
results.push(e);
|
||||
|
|
|
|||
|
|
@ -397,7 +397,7 @@ mod tests {
|
|||
harness.set_size(Vec2::new(size.width as f32, size.height as f32));
|
||||
|
||||
// Run the app for some more frames...
|
||||
harness.run();
|
||||
harness.run_ok();
|
||||
|
||||
let mut options = SnapshotOptions::default();
|
||||
// The Bézier Curve demo needs a threshold of 2.1 to pass on linux
|
||||
|
|
|
|||
|
|
@ -183,12 +183,13 @@ mod tests {
|
|||
|
||||
harness.get_by_role(Role::ComboBox).click();
|
||||
|
||||
harness.run();
|
||||
// Harness::run would fail because we keep requesting repaints to simulate progress.
|
||||
harness.run_ok();
|
||||
assert!(harness.ctx.memory(|mem| mem.any_popup_open()));
|
||||
assert!(harness.state().user_modal_open);
|
||||
|
||||
harness.press_key(Key::Escape);
|
||||
harness.run();
|
||||
harness.run_ok();
|
||||
assert!(!harness.ctx.memory(|mem| mem.any_popup_open()));
|
||||
assert!(harness.state().user_modal_open);
|
||||
}
|
||||
|
|
@ -238,17 +239,11 @@ mod tests {
|
|||
results.push(harness.try_snapshot("modals_1"));
|
||||
|
||||
harness.get_by_label("Save").click();
|
||||
// TODO(lucasmerlin): Remove these extra runs once run checks for repaint requests
|
||||
harness.run();
|
||||
harness.run();
|
||||
harness.run();
|
||||
harness.run_ok();
|
||||
results.push(harness.try_snapshot("modals_2"));
|
||||
|
||||
harness.get_by_label("Yes Please").click();
|
||||
// TODO(lucasmerlin): Remove these extra runs once run checks for repaint requests
|
||||
harness.run();
|
||||
harness.run();
|
||||
harness.run();
|
||||
harness.run_ok();
|
||||
results.push(harness.try_snapshot("modals_3"));
|
||||
|
||||
for result in results {
|
||||
|
|
@ -272,14 +267,11 @@ mod tests {
|
|||
initial_state,
|
||||
);
|
||||
|
||||
// TODO(lucasmerlin): Remove these extra runs once run checks for repaint requests
|
||||
harness.run();
|
||||
harness.run();
|
||||
harness.run();
|
||||
harness.run_ok();
|
||||
|
||||
harness.get_by_label("Yes Please").simulate_click();
|
||||
|
||||
harness.run();
|
||||
harness.run_ok();
|
||||
|
||||
// This snapshots should show the progress bar modal on top of the save modal.
|
||||
harness.snapshot("modals_backdrop_should_prevent_focusing_lower_area");
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:e89c730b462c2b60b90f2ac15fe9576e878a4906c223317c51344a0ec2b6d993
|
||||
size 27564
|
||||
oid sha256:4631f841b9e23833505af39eb1c45908013d3b1e1278d477bcedf6a460c71802
|
||||
size 27163
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:ea2c944af8bc1be42ec7c00be58dfaa23c92bca8957eda94f2ff10f5b4242562
|
||||
size 83358
|
||||
oid sha256:96e750ebfcc6ec2c130674407388c30cce844977cde19adfebf351fd08698a4f
|
||||
size 81726
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:c401ff91fff4051042528d398d2b2270a4ae924570e6332cf8f2c6774c845160
|
||||
size 11826
|
||||
oid sha256:b03613e597631da3b922ef3d696c4ce74cec41f86a2779fc5b084a316fc9e8e8
|
||||
size 11764
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:7efc1ff3e4e5bfd4216394f94ee7486c272a9ca1c980789f4ad143f89b0a7103
|
||||
size 21073
|
||||
oid sha256:76d77e2df39af248d004a023b238bb61ed598ab2bea3e0c6f2885f9537ec1103
|
||||
size 25988
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:d9c48cf928a17dd0980ba086aa004bde3a0040dcb82752d138c1df34f1ef3d2f
|
||||
size 21167
|
||||
oid sha256:003d905893b80ffc132a783155971ad3054229e9d6c046e2760c912559a66b3d
|
||||
size 20869
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:dc69c76eaa121e9e7782cfbbb68b5a23004d79862bae4af2e3ca3a29eff04bea
|
||||
size 136467
|
||||
oid sha256:99c94a09c0f6984909481189f9a1415ea90bd7c45e42b4b3763ee36f3d831a65
|
||||
size 133231
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:23187a9fb12a3ab7df4e2321aa25b493559923d61e82802f843ee29dcd932f7b
|
||||
size 24985
|
||||
oid sha256:7d8135b745cb95a7e7c7a26e73e160742f88ec177a2fa262215c4886d98ff172
|
||||
size 24403
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:7f433f3e8bff38a0aafd7e6cba5c5efe1abf484550a6f9e90008f8f5ea891497
|
||||
size 18113
|
||||
oid sha256:7b38828e423195628dcea09b0cbdd66aa4c077334ab7082efd358c7a3297009d
|
||||
size 17827
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:e5105ecf77852412c0dd904b96f0fec752f22e416df9932df4499d6d5a776f46
|
||||
size 22865
|
||||
oid sha256:c53403996451da14f7991ea61bd20b96dbc67eb67dd2041975dd6ce5015a6980
|
||||
size 22485
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:ebf0403bd599e5c00c2831f9c4032e8d20420212c9cd7fa875f1ae1cbbc8d3a7
|
||||
size 65902
|
||||
oid sha256:63673b070951246b98ca07613fa81496dbfdd10627bac3c9c4356ebff1a36b20
|
||||
size 64319
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:4e690dc73873ab75c030d3c0238e9d5b840f976dd8f4882dc1e930024d217838
|
||||
size 33323
|
||||
oid sha256:374b4095a3c7b827b80d6ab01b945458ae0128a2974c2af8aaf6b7e9fef6b459
|
||||
size 32554
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:e760210371dbf2a197f96a78d01b7480f0ae05d46bbb4e642276b2eb30847ec2
|
||||
size 37075
|
||||
oid sha256:5e756c90069803bb4d2821fff723877bffffd44b26613f5b06c8a042d6901ca4
|
||||
size 36578
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:fd02b208d0e4e306bbc9a54f25f5a3d20875a12182cef3224e6daa309b6cf453
|
||||
size 17898
|
||||
oid sha256:64fe3ef34aaf3104931954f4a39760b99944f42da13f866622ca0222b750f6be
|
||||
size 17731
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:341958da648a7db3374c4337cf057ae8e81c08c4a6de7e4f1cbe9c5b049f2e62
|
||||
size 25727
|
||||
oid sha256:dfa05d7f8c36b51c054253fbe8483c38637a12dde4a9d6051b226680820db319
|
||||
size 25097
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:8934cff7203d19b38df9d91729091ff5d1ad6c8d445fd9c1cb62b6df1bb8cb80
|
||||
size 263547
|
||||
oid sha256:eb631bd2608aec6c83f8815b9db0b28627bf82692fd2b1cb793119083b4f8ad1
|
||||
size 264496
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:5d61f58138798d701bb8dda2c3240eef69eb350df3168fb3aa4148e4fef3f77a
|
||||
size 24077
|
||||
oid sha256:e0870e9e1c9dc718690124a4d490f1061414f15fa40571e571d9319c3b65e74e
|
||||
size 23709
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:e4006e93663d02fe0f4485d2c163ab2b6feded787bee87ea15616fc0b36136d0
|
||||
size 188875
|
||||
oid sha256:532dbcbec94bb9c9fb8cc0665646790a459088e98077118b5fbb2112898e1a43
|
||||
size 183854
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:70b170ba7b8e51d9d9f766d7ce25068fa4265c4127e729af4f1adaacbb745d19
|
||||
size 120947
|
||||
oid sha256:3fd584643b68084ec4b65369e08d229e2d389551bbefa59c84ad4b58621593f7
|
||||
size 117754
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:157353a8c9bcb638a8be485489e4a232f348eae3cc4ceefe227d7970c7d1f8b3
|
||||
size 26256
|
||||
oid sha256:7e2b854d99c9b17d15ef92188cdac521d7c0635aef9ba457cd3801884a784009
|
||||
size 26159
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:cf0ddd39a45519dcf9027f691e856921c736d18e2eeafd16f0e086720121b6a7
|
||||
size 72286
|
||||
oid sha256:f0b7dc029de8e669d76f3be5e0800e973c354edcf7cefa239faed07c2cd5e0d5
|
||||
size 70452
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:914d37e326087f770994bcf3867a27d88050c57887a2b42c68414d311fa96003
|
||||
size 67698
|
||||
oid sha256:64ba40810a6480e511e8d198b0dfb39e8b220eb2f5592877e27b17ee8d47b9c3
|
||||
size 66387
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:b0fdf8ce329883450e071e4733c3904577999d18ac61c922c7caacbec09dfda7
|
||||
size 21661
|
||||
oid sha256:0a8151f5bd01b2cb5183c532d11f57bbb7e8cc1e77a3c4b890537d157922c961
|
||||
size 21261
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:375b71a8ac5b0e48f3c67a089ef0e8a4fd17f8eb21fa535422099c29c2747e27
|
||||
size 59991
|
||||
oid sha256:96ce36fcc334793801ab724c711f592faf086a9c98c812684e6b76010e9d1974
|
||||
size 59714
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:aa96b1e3733e4af94a6cb6ec765c3f3581df2175e75831eb00bd42df2e7a2708
|
||||
size 13285
|
||||
oid sha256:8155d93b78692ced67ddee4011526ef627838ede78351871df5feef8aa512857
|
||||
size 13141
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:18880dfaf5d198876c4db97ebd6313d59755a3e8298567f2b2fa91dcc21699c5
|
||||
size 35607
|
||||
oid sha256:bf6da022ab97f9d4b862cc8e91bdfd7f9785a3ab0540aa1c2bd2646bd30a3450
|
||||
size 35115
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:d626b310439bff13487548bbba8b516886c13049824a7f5dd902f6dffb3c5ba4
|
||||
size 48234
|
||||
oid sha256:035b35ed053cabd5022d9a97f7d4d5a79d194c9f14594e7602ecd9ef94c24ae5
|
||||
size 48053
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:ed2a356452d792e32bea57f044da9d86da27fd8504826dd6b87618a53519ea6a
|
||||
size 522556
|
||||
oid sha256:3562bb87b155b2c406a72a651ffb1991305aa1e15273ce9f32cedc5766318537
|
||||
size 554922
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:0d04a5854528c6141f7def6f9229c51c6d2d4c87e2f656be4d149e7b2b852976
|
||||
size 729056
|
||||
oid sha256:ba6c0bd127ab02375f2ae5fbc3eeef33a1bdf074cbb180de2733c700b81df3e5
|
||||
size 771069
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:e6e5c1a745e357faa7b98f7a2cd1ca139c4a14be154b9d21feb8030933acfdb7
|
||||
size 867552
|
||||
oid sha256:d85ab6d04059009fd2c3ad8001332b27e710c46c9300f2f1f409b882c49211dc
|
||||
size 918967
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:7d9f4a37541fd1a0754c1cb1f3a2d4a76f03d67ca4e5596c8e6982d691d29dea
|
||||
size 980286
|
||||
oid sha256:a64f1bdec565357fe4dee3acb46b12eeb0492b522fb3bb9697d39dadce2e8c21
|
||||
size 1039455
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:4d1c99867202e16500146b7146a32fd83d70d60f5ac94aae4ca405a6377e4625
|
||||
size 1066559
|
||||
oid sha256:5ca008dca03372bb334564e55fa2d1d25a36751a43df6001a1c1cf3e4db9bcd4
|
||||
size 1130930
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:08fc1c89fd2d04aa12c75a1829dacfff090e322c65ad969648799833e1b072eb
|
||||
size 1235574
|
||||
oid sha256:7f695127e7fe6cb3b752a0acd71db85d51d2de68e45051a7afe91f4d960acf27
|
||||
size 1311641
|
||||
|
|
|
|||
|
|
@ -8,6 +8,8 @@ use std::marker::PhantomData;
|
|||
pub struct HarnessBuilder<State = ()> {
|
||||
pub(crate) screen_rect: Rect,
|
||||
pub(crate) pixels_per_point: f32,
|
||||
pub(crate) max_steps: u64,
|
||||
pub(crate) step_dt: f32,
|
||||
pub(crate) state: PhantomData<State>,
|
||||
pub(crate) renderer: Box<dyn TestRenderer>,
|
||||
}
|
||||
|
|
@ -19,6 +21,8 @@ impl<State> Default for HarnessBuilder<State> {
|
|||
pixels_per_point: 1.0,
|
||||
state: PhantomData,
|
||||
renderer: Box::new(LazyRenderer::default()),
|
||||
max_steps: 4,
|
||||
step_dt: 1.0 / 4.0,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -40,6 +44,26 @@ impl<State> HarnessBuilder<State> {
|
|||
self
|
||||
}
|
||||
|
||||
/// Set the maximum number of steps to run when calling [`Harness::run`].
|
||||
///
|
||||
/// Default is 4.
|
||||
/// With the default `step_dt`, this means 1 second of simulation.
|
||||
#[inline]
|
||||
pub fn with_max_steps(mut self, max_steps: u64) -> Self {
|
||||
self.max_steps = max_steps;
|
||||
self
|
||||
}
|
||||
|
||||
/// Set the time delta for a single [`Harness::step`].
|
||||
///
|
||||
/// Default is 1.0 / 4.0 (4fps).
|
||||
/// The default is low so we don't waste cpu waiting for animations.
|
||||
#[inline]
|
||||
pub fn with_step_dt(mut self, step_dt: f32) -> Self {
|
||||
self.step_dt = step_dt;
|
||||
self
|
||||
}
|
||||
|
||||
/// Set the [`TestRenderer`] to use for rendering.
|
||||
///
|
||||
/// By default, a [`LazyRenderer`] is used.
|
||||
|
|
|
|||
|
|
@ -10,7 +10,9 @@ mod snapshot;
|
|||
|
||||
#[cfg(feature = "snapshot")]
|
||||
pub use snapshot::*;
|
||||
use std::fmt::{Debug, Formatter};
|
||||
use std::fmt::{Debug, Display, Formatter};
|
||||
use std::time::Duration;
|
||||
|
||||
mod app_kind;
|
||||
mod renderer;
|
||||
#[cfg(feature = "wgpu")]
|
||||
|
|
@ -26,9 +28,26 @@ use crate::event::EventState;
|
|||
pub use builder::*;
|
||||
pub use renderer::*;
|
||||
|
||||
use egui::{Modifiers, Pos2, Rect, Vec2, ViewportId};
|
||||
use egui::{Modifiers, Pos2, Rect, RepaintCause, Vec2, ViewportId};
|
||||
use kittest::{Node, Queryable};
|
||||
|
||||
pub struct ExceededMaxStepsError {
|
||||
pub max_steps: u64,
|
||||
pub repaint_causes: Vec<RepaintCause>,
|
||||
}
|
||||
|
||||
impl Display for ExceededMaxStepsError {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
write!(
|
||||
f,
|
||||
"Harness::run exceeded max_steps ({}). If your expect your ui to keep repainting \
|
||||
(e.g. when showing a spinner) call Harness::step or Harness::run_steps instead.\
|
||||
\nRepaint causes: {:#?}",
|
||||
self.max_steps, self.repaint_causes,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/// The test Harness. This contains everything needed to run the test.
|
||||
/// Create a new Harness using [`Harness::new`] or [`Harness::builder`].
|
||||
///
|
||||
|
|
@ -45,6 +64,8 @@ pub struct Harness<'a, State = ()> {
|
|||
response: Option<egui::Response>,
|
||||
state: State,
|
||||
renderer: Box<dyn TestRenderer>,
|
||||
max_steps: u64,
|
||||
step_dt: f32,
|
||||
}
|
||||
|
||||
impl<'a, State> Debug for Harness<'a, State> {
|
||||
|
|
@ -60,14 +81,24 @@ impl<'a, State> Harness<'a, State> {
|
|||
mut state: State,
|
||||
ctx: Option<egui::Context>,
|
||||
) -> Self {
|
||||
let HarnessBuilder {
|
||||
screen_rect,
|
||||
pixels_per_point,
|
||||
max_steps,
|
||||
step_dt,
|
||||
state: _,
|
||||
mut renderer,
|
||||
} = builder;
|
||||
let ctx = ctx.unwrap_or_default();
|
||||
ctx.enable_accesskit();
|
||||
// Disable cursor blinking so it doesn't interfere with snapshots
|
||||
ctx.all_styles_mut(|style| style.visuals.text_cursor.blink = false);
|
||||
let mut input = egui::RawInput {
|
||||
screen_rect: Some(builder.screen_rect),
|
||||
screen_rect: Some(screen_rect),
|
||||
..Default::default()
|
||||
};
|
||||
let viewport = input.viewports.get_mut(&ViewportId::ROOT).unwrap();
|
||||
viewport.native_pixels_per_point = Some(builder.pixels_per_point);
|
||||
viewport.native_pixels_per_point = Some(pixels_per_point);
|
||||
|
||||
let mut response = None;
|
||||
|
||||
|
|
@ -77,7 +108,6 @@ impl<'a, State> Harness<'a, State> {
|
|||
response = app.run(ctx, &mut state, false);
|
||||
});
|
||||
|
||||
let mut renderer = builder.renderer;
|
||||
renderer.handle_delta(&output.textures_delta);
|
||||
|
||||
let mut harness = Self {
|
||||
|
|
@ -96,9 +126,11 @@ impl<'a, State> Harness<'a, State> {
|
|||
event_state: EventState::default(),
|
||||
state,
|
||||
renderer,
|
||||
max_steps,
|
||||
step_dt,
|
||||
};
|
||||
// Run the harness until it is stable, ensuring that all Areas are shown and animations are done
|
||||
harness.run();
|
||||
harness.run_ok();
|
||||
harness
|
||||
}
|
||||
|
||||
|
|
@ -188,7 +220,8 @@ impl<'a, State> Harness<'a, State> {
|
|||
}
|
||||
|
||||
/// Run a frame.
|
||||
/// This will call the app closure with the current context and update the Harness.
|
||||
/// This will call the app closure with the queued events and current context and
|
||||
/// update the Harness.
|
||||
pub fn step(&mut self) {
|
||||
self._step(false);
|
||||
}
|
||||
|
|
@ -200,6 +233,8 @@ impl<'a, State> Harness<'a, State> {
|
|||
}
|
||||
}
|
||||
|
||||
self.input.predicted_dt = self.step_dt;
|
||||
|
||||
let mut output = self.ctx.run(self.input.take(), |ctx| {
|
||||
self.response = self.app.run(ctx, &mut self.state, sizing_pass);
|
||||
});
|
||||
|
|
@ -215,22 +250,95 @@ impl<'a, State> Harness<'a, State> {
|
|||
}
|
||||
|
||||
/// Resize the test harness to fit the contents. This only works when creating the Harness via
|
||||
/// [`Harness::new_ui`] or [`HarnessBuilder::build_ui`].
|
||||
/// [`Harness::new_ui`] / [`Harness::new_ui_state`] or
|
||||
/// [`HarnessBuilder::build_ui`] / [`HarnessBuilder::build_ui_state`].
|
||||
pub fn fit_contents(&mut self) {
|
||||
self._step(true);
|
||||
if let Some(response) = &self.response {
|
||||
self.set_size(response.rect.size());
|
||||
}
|
||||
self.run();
|
||||
self.run_ok();
|
||||
}
|
||||
|
||||
/// Run a few frames.
|
||||
/// This will soon be changed to run the app until it is "stable", meaning
|
||||
/// Run until
|
||||
/// - all animations are done
|
||||
/// - no more repaints are requested
|
||||
pub fn run(&mut self) {
|
||||
const STEPS: usize = 2;
|
||||
for _ in 0..STEPS {
|
||||
///
|
||||
/// Returns the number of frames that were run.
|
||||
///
|
||||
/// # Panics
|
||||
/// Panics if the number of steps exceeds the maximum number of steps set
|
||||
/// in [`HarnessBuilder::with_max_steps`].
|
||||
///
|
||||
/// See also:
|
||||
/// - [`Harness::try_run`].
|
||||
/// - [`Harness::run_ok`].
|
||||
/// - [`Harness::step`].
|
||||
/// - [`Harness::run_steps`].
|
||||
#[track_caller]
|
||||
pub fn run(&mut self) -> u64 {
|
||||
match self.try_run() {
|
||||
Ok(steps) => steps,
|
||||
Err(err) => {
|
||||
panic!("{err}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Run until
|
||||
/// - all animations are done
|
||||
/// - no more repaints are requested
|
||||
/// - the maximum number of steps is reached (See [`HarnessBuilder::with_max_steps`])
|
||||
///
|
||||
/// Returns the number of steps that were run.
|
||||
///
|
||||
/// # Errors
|
||||
/// Returns an error if the maximum number of steps is exceeded.
|
||||
///
|
||||
/// See also:
|
||||
/// - [`Harness::run`].
|
||||
/// - [`Harness::run_ok`].
|
||||
/// - [`Harness::step`].
|
||||
/// - [`Harness::run_steps`].
|
||||
pub fn try_run(&mut self) -> Result<u64, ExceededMaxStepsError> {
|
||||
let mut steps = 0;
|
||||
loop {
|
||||
steps += 1;
|
||||
self.step();
|
||||
// We only care about immediate repaints
|
||||
if self.root_viewport_output().repaint_delay != Duration::ZERO {
|
||||
break;
|
||||
}
|
||||
if steps > self.max_steps {
|
||||
return Err(ExceededMaxStepsError {
|
||||
max_steps: self.max_steps,
|
||||
repaint_causes: self.ctx.repaint_causes(),
|
||||
});
|
||||
}
|
||||
}
|
||||
Ok(steps)
|
||||
}
|
||||
|
||||
/// Run until
|
||||
/// - all animations are done
|
||||
/// - no more repaints are requested
|
||||
/// - the maximum number of steps is reached (See [`HarnessBuilder::with_max_steps`])
|
||||
///
|
||||
/// Returns the number of steps that were run, or None if the maximum number of steps was exceeded.
|
||||
///
|
||||
/// See also:
|
||||
/// - [`Harness::run`].
|
||||
/// - [`Harness::try_run`].
|
||||
/// - [`Harness::step`].
|
||||
/// - [`Harness::run_steps`].
|
||||
pub fn run_ok(&mut self) -> Option<u64> {
|
||||
self.try_run().ok()
|
||||
}
|
||||
|
||||
/// Run a number of steps.
|
||||
/// Equivalent to calling [`Harness::step`] x times.
|
||||
pub fn run_steps(&mut self, steps: usize) {
|
||||
for _ in 0..steps {
|
||||
self.step();
|
||||
}
|
||||
}
|
||||
|
|
@ -297,6 +405,14 @@ impl<'a, State> Harness<'a, State> {
|
|||
pub fn render(&mut self) -> Result<image::RgbaImage, String> {
|
||||
self.renderer.render(&self.ctx, &self.output)
|
||||
}
|
||||
|
||||
/// Get the root viewport output
|
||||
fn root_viewport_output(&self) -> &egui::ViewportOutput {
|
||||
self.output
|
||||
.viewport_output
|
||||
.get(&ViewportId::ROOT)
|
||||
.expect("Missing root viewport")
|
||||
}
|
||||
}
|
||||
|
||||
/// Utilities for stateless harnesses.
|
||||
|
|
|
|||
Loading…
Reference in New Issue