Skip to content

Commit

Permalink
Small fixes and improvements
Browse files Browse the repository at this point in the history
  • Loading branch information
lucasmerlin committed Dec 29, 2024
1 parent d098ee5 commit 841edbb
Show file tree
Hide file tree
Showing 15 changed files with 57 additions and 61 deletions.
2 changes: 1 addition & 1 deletion crates/eframe/src/web/web_painter_wgpu.rs
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ impl WebPainterWgpu {
let render_state = RenderState::create(
&options.wgpu_options,
&instance,
&surface,
Some(&surface),
depth_format,
1,
options.dithering,
Expand Down
5 changes: 4 additions & 1 deletion crates/egui-wgpu/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -188,7 +188,10 @@ impl RenderState {

let capabilities = {
profiling::scope!("get_capabilities");
surface.map_or_else(|| vec![TextureFormat::Rgba8Unorm], |s| s.get_capabilities(&adapter).formats)
surface.map_or_else(
|| vec![TextureFormat::Rgba8Unorm],
|s| s.get_capabilities(&adapter).formats,
)
};
let target_format = crate::preferred_framebuffer_format(&capabilities)?;

Expand Down
4 changes: 1 addition & 3 deletions crates/egui_demo_app/tests/test_demo_app.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
use eframe::egui_wgpu::WgpuSetup;
use egui::accesskit::Role;
use egui::Vec2;
use egui_demo_app::{Anchor, WrapApp};
use egui_kittest::kittest::Queryable;
use std::sync::Arc;

#[test]
fn test_demo_app() {
Expand Down Expand Up @@ -69,7 +67,7 @@ fn test_demo_app() {

harness.run();

if let Err(e) = harness.try_wgpu_snapshot(&anchor.to_string()) {
if let Err(e) = harness.try_snapshot(&anchor.to_string()) {
results.push(e);
}
}
Expand Down
2 changes: 1 addition & 1 deletion crates/egui_demo_lib/src/demo/demo_app_windows.rs
Original file line number Diff line number Diff line change
Expand Up @@ -405,7 +405,7 @@ mod tests {
options.threshold = 2.1;
}

let result = harness.try_wgpu_snapshot_options(&format!("demos/{name}"), &options);
let result = harness.try_snapshot_options(&format!("demos/{name}"), &options);
if let Err(err) = result {
errors.push(err.to_string());
}
Expand Down
8 changes: 4 additions & 4 deletions crates/egui_demo_lib/src/demo/modals.rs
Original file line number Diff line number Diff line change
Expand Up @@ -235,21 +235,21 @@ mod tests {
let mut results = Vec::new();

harness.run();
results.push(harness.try_wgpu_snapshot("modals_1"));
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();
results.push(harness.try_wgpu_snapshot("modals_2"));
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();
results.push(harness.try_wgpu_snapshot("modals_3"));
results.push(harness.try_snapshot("modals_3"));

for result in results {
result.unwrap();
Expand Down Expand Up @@ -282,6 +282,6 @@ mod tests {
harness.run();

// This snapshots should show the progress bar modal on top of the save modal.
harness.wgpu_snapshot("modals_backdrop_should_prevent_focusing_lower_area");
harness.snapshot("modals_backdrop_should_prevent_focusing_lower_area");
}
}
2 changes: 1 addition & 1 deletion crates/egui_demo_lib/src/demo/widget_gallery.rs
Original file line number Diff line number Diff line change
Expand Up @@ -307,6 +307,6 @@ mod tests {

harness.fit_contents();

harness.wgpu_snapshot("widget_gallery");
harness.snapshot("widget_gallery");
}
}
2 changes: 1 addition & 1 deletion crates/egui_demo_lib/src/rendering_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -703,7 +703,7 @@ mod tests {

harness.fit_contents();

let result = harness.try_wgpu_snapshot(&format!("rendering_test/dpi_{dpi:.2}"));
let result = harness.try_snapshot(&format!("rendering_test/dpi_{dpi:.2}"));
if let Err(err) = result {
errors.push(err);
}
Expand Down
4 changes: 2 additions & 2 deletions crates/egui_kittest/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,13 +29,13 @@ fn main() {

// You can even render the ui and do image snapshot tests
#[cfg(all(feature = "wgpu", feature = "snapshot"))]
harness.wgpu_snapshot("readme_example");
harness.snapshot("readme_example");
}
```

## Snapshot testing
There is a snapshot testing feature. To create snapshot tests, enable the `snapshot` and `wgpu` features.
Once enabled, you can call `Harness::wgpu_snapshot` to render the ui and save the image to the `tests/snapshots` directory.
Once enabled, you can call `Harness::snapshot` to render the ui and save the image to the `tests/snapshots` directory.

To update the snapshots, run your tests with `UPDATE_SNAPSHOTS=true`, so e.g. `UPDATE_SNAPSHOTS=true cargo test`.
Running with `UPDATE_SNAPSHOTS=true` will still cause the tests to fail, but on the next run, the tests should pass.
Expand Down
4 changes: 2 additions & 2 deletions crates/egui_kittest/src/app_kind.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,10 @@ type AppKindUiState<'a, State> = Box<dyn FnMut(&mut egui::Ui, &mut State) + 'a>;
type AppKindContext<'a> = Box<dyn FnMut(&egui::Context) + 'a>;
type AppKindUi<'a> = Box<dyn FnMut(&mut egui::Ui) + 'a>;

/// In order to access the [eframe::App] trait from the generic [State], we store a function pointer
/// In order to access the [`eframe::App`] trait from the generic `State`, we store a function pointer
/// here that will return the dyn trait from the struct. In the builder we have the correct where
/// clause to be able to create this.
/// Later we can use it anywhere to get the [eframe::App] from the [State].
/// Later we can use it anywhere to get the [`eframe::App`] from the `State`.
#[cfg(feature = "eframe")]
type AppKindEframe<'a, State> = (fn(&mut State) -> &mut dyn eframe::App, eframe::Frame);

Expand Down
23 changes: 12 additions & 11 deletions crates/egui_kittest/src/builder.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
use crate::app_kind::AppKind;
use crate::wgpu::WgpuTestRenderer;
use crate::{Harness, LazyRenderer, TestRenderer};
use egui::{Pos2, Rect, Vec2};
use std::marker::PhantomData;
use crate::wgpu::WgpuTestRenderer;

/// Builder for [`Harness`].
pub struct HarnessBuilder<State = ()> {
Expand Down Expand Up @@ -40,20 +40,26 @@ impl<State> HarnessBuilder<State> {
self
}

/// Set the [`TestRenderer`] to use for rendering.
///
/// By default, a [`LazyRenderer`] is used.
#[inline]
pub fn renderer(mut self, renderer: impl TestRenderer + 'static) -> Self {
self.renderer = Box::new(renderer);
self
}

/// Enable wgpu rendering with a default setup suitable for testing.
///
/// This sets up a [`WgpuTestRenderer`] with the default setup.
#[cfg(feature = "wgpu")]
pub fn wgpu(mut self) -> Self {
pub fn wgpu(self) -> Self {
self.renderer(WgpuTestRenderer::default())
}

/// Enable wgpu rendering with the given setup.
#[cfg(feature = "wgpu")]
pub fn wgpu_setup(mut self, setup: egui_wgpu::WgpuSetup) -> Self {
pub fn wgpu_setup(self, setup: egui_wgpu::WgpuSetup) -> Self {
self.renderer(WgpuTestRenderer::from_setup(setup))
}

Expand Down Expand Up @@ -86,12 +92,7 @@ impl<State> HarnessBuilder<State> {
app: impl FnMut(&egui::Context, &mut State) + 'a,
state: State,
) -> Harness<'a, State> {
Harness::from_builder(
self,
AppKind::ContextState(Box::new(app)),
state,
None,
)
Harness::from_builder(self, AppKind::ContextState(Box::new(app)), state, None)
}

/// Create a new Harness with the given ui closure and a state.
Expand Down Expand Up @@ -124,10 +125,10 @@ impl<State> HarnessBuilder<State> {
}

/// Create a new [Harness] from the given eframe creation closure.
/// The app can be accessed via the [Harness::state] / [Harness::state_mut] methods.
/// The app can be accessed via the [`Harness::state`] / [`Harness::state_mut`] methods.
#[cfg(feature = "eframe")]
pub fn build_eframe<'a>(
mut self,
self,
build: impl FnOnce(&mut eframe::CreationContext<'a>) -> State,
) -> Harness<'a, State>
where
Expand Down
8 changes: 3 additions & 5 deletions crates/egui_kittest/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,22 +12,20 @@ mod snapshot;
pub use snapshot::*;
use std::fmt::{Debug, Formatter};
mod app_kind;
mod renderer;
#[cfg(feature = "wgpu")]
mod texture_to_image;
#[cfg(feature = "wgpu")]
pub mod wgpu;
mod renderer;

pub use kittest;
use std::mem;

use crate::app_kind::AppKind;
use crate::event::EventState;
pub use builder::*;
pub use renderer::*;
use egui::{Modifiers, Pos2, Rect, TexturesDelta, Vec2, ViewportId};
use egui::{Modifiers, Pos2, Rect, Vec2, ViewportId};
use kittest::{Node, Queryable};
use egui_wgpu::RenderState;
pub use renderer::*;

/// The test Harness. This contains everything needed to run the test.
/// Create a new Harness using [`Harness::new`] or [`Harness::builder`].
Expand Down
12 changes: 4 additions & 8 deletions crates/egui_kittest/src/renderer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,22 +2,18 @@ use egui::{Context, FullOutput, TexturesDelta};
use image::RgbaImage;

pub trait TestRenderer {
/// We use this to pass the glow / wgpu render state to [eframe::Frame].
/// We use this to pass the glow / wgpu render state to [`eframe::Frame`].
#[cfg(feature = "eframe")]
fn setup_eframe(&self, cc: &mut eframe::CreationContext<'_>, frame: &mut eframe::Frame) {}
fn setup_eframe(&self, _cc: &mut eframe::CreationContext<'_>, _frame: &mut eframe::Frame) {}

/// Handle a [`TexturesDelta`] by updating the renderer's textures.
fn handle_delta(&mut self, delta: &TexturesDelta);

/// Render the [`Harness`] and return the resulting image.
/// Render the [`crate::Harness`] and return the resulting image.
///
/// # Errors
/// Returns an error if the rendering fails.
fn render(
&mut self,
ctx: &egui::Context,
output: &egui::FullOutput,
) -> Result<image::RgbaImage, String>;
fn render(&mut self, ctx: &Context, output: &FullOutput) -> Result<RgbaImage, String>;
}

pub enum LazyRenderer {
Expand Down
28 changes: 14 additions & 14 deletions crates/egui_kittest/src/snapshot.rs
Original file line number Diff line number Diff line change
Expand Up @@ -319,25 +319,25 @@ pub fn image_snapshot(current: &image::RgbaImage, name: &str) {

#[cfg(feature = "wgpu")]
impl<State> Harness<'_, State> {
/// Render a image using a default [`crate::wgpu::TestRenderer`] and compare it to the snapshot
/// Render a image using the setup [`crate::TestRenderer`] and compare it to the snapshot
/// with custom options.
///
/// If you want to change the default options for your whole project, you could create an
/// [extension trait](http://xion.io/post/code/rust-extension-traits.html) to create a
/// new `my_image_snapshot` function on the Harness that calls this function with the desired options.
/// You could additionally use the
/// [disallowed_methods](https://rust-lang.github.io/rust-clippy/master/#disallowed_methods)
/// lint to disable use of the [`Harness::wgpu_snapshot`] to prevent accidentally using the wrong defaults.
/// lint to disable use of the [`Harness::snapshot`] to prevent accidentally using the wrong defaults.
///
/// The snapshot files will be saved under [`SnapshotOptions::output_path`].
/// The snapshot will be saved under `{output_path}/{name}.png`.
/// The new image from the most recent test run will be saved under `{output_path}/{name}.new.png`.
/// If new image didn't match the snapshot, a diff image will be saved under `{output_path}/{name}.diff.png`.
///
/// # Errors
/// Returns a [`SnapshotError`] if the image does not match the snapshot, if there was an
/// Returns a [`SnapshotError`] if the image does not match the snapshot, if there was an
/// error reading or writing the snapshot, if the rendering fails or if no default renderer is available.
pub fn try_wgpu_snapshot_options(
pub fn try_snapshot_options(
&mut self,
name: &str,
options: &SnapshotOptions,
Expand All @@ -348,30 +348,30 @@ impl<State> Harness<'_, State> {
try_image_snapshot_options(&image, name, options)
}

/// Render a image using a default [`crate::wgpu::TestRenderer`] and compare it to the snapshot.
/// Render a image using the setup [`crate::TestRenderer`] and compare it to the snapshot.
/// The snapshot will be saved under `tests/snapshots/{name}.png`.
/// The new image from the last test run will be saved under `tests/snapshots/{name}.new.png`.
/// If new image didn't match the snapshot, a diff image will be saved under `tests/snapshots/{name}.diff.png`.
///
/// # Errors
/// Returns a [`SnapshotError`] if the image does not match the snapshot, if there was an
/// Returns a [`SnapshotError`] if the image does not match the snapshot, if there was an
/// error reading or writing the snapshot, if the rendering fails or if no default renderer is available.
pub fn try_wgpu_snapshot(&mut self, name: &str) -> Result<(), SnapshotError> {
pub fn try_snapshot(&mut self, name: &str) -> Result<(), SnapshotError> {
let image = self
.render()
.map_err(|err| SnapshotError::RenderError { err })?;
try_image_snapshot(&image, name)
}

/// Render a image using a default [`crate::wgpu::TestRenderer`] and compare it to the snapshot
/// Render a image using the setup [`crate::TestRenderer`] and compare it to the snapshot
/// with custom options.
///
/// If you want to change the default options for your whole project, you could create an
/// [extension trait](http://xion.io/post/code/rust-extension-traits.html) to create a
/// new `my_image_snapshot` function on the Harness that calls this function with the desired options.
/// You could additionally use the
/// [disallowed_methods](https://rust-lang.github.io/rust-clippy/master/#disallowed_methods)
/// lint to disable use of the [`Harness::wgpu_snapshot`] to prevent accidentally using the wrong defaults.
/// lint to disable use of the [`Harness::snapshot`] to prevent accidentally using the wrong defaults.
///
/// The snapshot files will be saved under [`SnapshotOptions::output_path`].
/// The snapshot will be saved under `{output_path}/{name}.png`.
Expand All @@ -382,16 +382,16 @@ impl<State> Harness<'_, State> {
/// Panics if the image does not match the snapshot, if there was an error reading or writing the
/// snapshot, if the rendering fails or if no default renderer is available.
#[track_caller]
pub fn wgpu_snapshot_options(&mut self, name: &str, options: &SnapshotOptions) {
match self.try_wgpu_snapshot_options(name, options) {
pub fn snapshot_options(&mut self, name: &str, options: &SnapshotOptions) {
match self.try_snapshot_options(name, options) {
Ok(_) => {}
Err(err) => {
panic!("{}", err);
}
}
}

/// Render a image using a default [`crate::TestRenderer`] and compare it to the snapshot.
/// Render a image using the setup [`crate::TestRenderer`] and compare it to the snapshot.
/// The snapshot will be saved under `tests/snapshots/{name}.png`.
/// The new image from the last test run will be saved under `tests/snapshots/{name}.new.png`.
/// If new image didn't match the snapshot, a diff image will be saved under `tests/snapshots/{name}.diff.png`.
Expand All @@ -400,8 +400,8 @@ impl<State> Harness<'_, State> {
/// Panics if the image does not match the snapshot, if there was an error reading or writing the
/// snapshot, if the rendering fails or if no default renderer is available.
#[track_caller]
pub fn wgpu_snapshot(&mut self, name: &str) {
match self.try_wgpu_snapshot(name) {
pub fn snapshot(&mut self, name: &str) {
match self.try_snapshot(name) {
Ok(_) => {}
Err(err) => {
panic!("{}", err);
Expand Down
12 changes: 6 additions & 6 deletions crates/egui_kittest/src/wgpu.rs
Original file line number Diff line number Diff line change
@@ -1,25 +1,25 @@
use crate::texture_to_image::texture_to_image;
use egui::TexturesDelta;
use egui_wgpu::wgpu::{Backends, StoreOp, TextureFormat};
use egui_wgpu::{wgpu, RenderState, ScreenDescriptor, WgpuSetup};
use image::RgbaImage;
use std::iter::once;
use std::sync::Arc;
use wgpu::Maintain;
use egui::TexturesDelta;

// TODO: Replace this with the setup from https://github.com/emilk/egui/pull/5506
// TODO(#5506): Replace this with the setup from https://github.com/emilk/egui/pull/5506
pub fn default_wgpu_setup() -> egui_wgpu::WgpuSetup {
egui_wgpu::WgpuSetup::CreateNew {
supported_backends: Backends::all(),
device_descriptor: Arc::new(|a| wgpu::DeviceDescriptor::default()),
device_descriptor: Arc::new(|_| wgpu::DeviceDescriptor::default()),
power_preference: wgpu::PowerPreference::default(),
}
}

pub(crate) fn create_render_state(setup: WgpuSetup) -> egui_wgpu::RenderState {
let instance = match &setup {
WgpuSetup::Existing { instance, .. } => instance.clone(),
_ => Default::default(),
WgpuSetup::CreateNew { .. } => Default::default(),
};

pollster::block_on(egui_wgpu::RenderState::create(
Expand All @@ -36,7 +36,7 @@ pub(crate) fn create_render_state(setup: WgpuSetup) -> egui_wgpu::RenderState {
.expect("Failed to create render state")
}

/// Utility to render snapshots from a [`Harness`] using [`egui_wgpu`].
/// Utility to render snapshots from a [`crate::Harness`] using [`egui_wgpu`].
pub struct WgpuTestRenderer {
render_state: RenderState,
}
Expand Down Expand Up @@ -82,7 +82,7 @@ impl crate::TestRenderer for WgpuTestRenderer {
}
}

/// Render the [`Harness`] and return the resulting image.
/// Render the [`crate::Harness`] and return the resulting image.
fn render(
&mut self,
ctx: &egui::Context,
Expand Down
2 changes: 1 addition & 1 deletion crates/egui_kittest/tests/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,5 @@ fn test_shrink() {
harness.fit_contents();

#[cfg(all(feature = "snapshot", feature = "wgpu"))]
harness.wgpu_snapshot("test_shrink");
harness.snapshot("test_shrink");
}

0 comments on commit 841edbb

Please sign in to comment.