1
0
mirror of https://github.com/emilk/egui.git synced 2026-08-29 04:40:03 -04:00
Commit Graph

40 Commits

Author SHA1 Message Date
Emil Ernerfeldt
34b39d564b Enable the clippy::pedantic lint group (#8429)
Instead of opting in to pedantic lints one by one, enable the whole
group and opt out of the noisy ones.

64% of the pedantic lints were already listed individually. This deletes
90 explicit lint lines, enables 51 pedantic lints we never listed, and
picks up new pedantic lints for free. Each opt-out carries its hit
count, so the cost of turning one back on is visible.

`restriction` and `nursery` stay opt-in per lint.

Stacked on top of #8430, which fixes the one real bug the new lints
found.

* [x] I have followed the instructions in the PR template

---------

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-18 06:55:53 +02:00
Emil Ernerfeldt
6aea7eff94 Enable the clippy::std_instead_of_core lint (#8394)
Prefer `core::` over `std::` where either work

* Part of https://github.com/emilk/egui/issues/5735
2026-08-06 13:19:13 +02:00
Lucas Meurer
6268c84d8a Prevent accidentally dropping TexturesDelta (#8356)
We had a ton of issues around `TexturesDelta` that weren't properly
applied because we early-out of some function:
* https://github.com/emilk/egui/pull/8313
* https://github.com/emilk/egui/pull/8250
* https://github.com/emilk/egui/pull/8279

This PR changes texture updates, so that we always store them after
taking them out of `FullOutput` and keep the delta around until it's
actually applied (by passing &mut refs and draining instead of
iterating). So even if we add a new early return somewhere, that can't
break texture updates.

It also optimizes `TexturesDelta::append` by dropping any previous
deltas if there's a new `whole` delta or a `free`.

It also adds a debug assert that any `TexturesDelta` is empty when
dropped, as an additional safeguard in case the bug sneaks back in.

---------

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-07-29 16:16:48 +00:00
Lucas Meurer
d06f5b5dfc Handle ViewportCommand::InnerSize in egui_kittest (#8350)
Useful to support resizing headless apps via `egui_inspection`
2026-07-28 10:54:45 +02:00
Lucas Meurer
2cb071f7f6 Remove Modifiers from RawInput and make it a egui::Event (#8336)
- needs #8335 

Previously it was impossible to correctly set modifiers via egui
inspection, since that only passes egui::Event and egui::Event had no
way to generally express modifiers.
Now modifiers are passed to egui as a Event and not as a field of
`RawInput`.

---------

Co-authored-by: Emil Ernerfeldt <emil.ernerfeldt@gmail.com>
2026-07-27 14:17:22 +00:00
Lucas Meurer
600286d056 Handle ViewportCommand::Screenshot in kittest (#8256)
Makes it possible to use egui_mcp to drive apps headlessly via kittest
2026-06-24 19:58:30 +02:00
Emil Ernerfeldt
46c20810ba Remove impl Into<f32> arguments (#8194)
* Closes https://github.com/emilk/egui/issues/8179
2026-05-25 10:59:03 +02:00
Jochen Görtler
07c6e0de0f Exclude take_app from wasm32 in egui_kittest (#8178)
Otherwise `egui` won't compile for `wasm32` targets anymore.

A bit odd that this was not caught in CI.
2026-05-19 18:00:50 +02:00
Emil Ernerfeldt
56aabda7b3 Add Harness::spawn_eframe_app (#8120)
This lets you start up the test app from within the test itself, which
can be very useful when you have a specific test scenario set up that
you need to debug.

### Related
* Previous attempt: https://github.com/emilk/egui/pull/5418

### macOS
On macOS, you may only run UIs on the main loop, so you need a few
additional steps. Not ideal, but works!


```diff
diff --git a/crates/egui_demo_app/Cargo.toml b/crates/egui_demo_app/Cargo.toml
index f9a153268..4e0cc14ee 100644
--- a/crates/egui_demo_app/Cargo.toml
+++ b/crates/egui_demo_app/Cargo.toml
@@ -84,3 +84,7 @@ web-sys.workspace = true
 
 [dev-dependencies]
 egui_kittest = { workspace = true, features = ["eframe", "snapshot", "wgpu"] }
+
+[[test]]
+name = "test_demo_app"
+harness = false
diff --git a/crates/egui_demo_app/tests/test_demo_app.rs b/crates/egui_demo_app/tests/test_demo_app.rs
index e083c8455..7ad9ed516 100644
--- a/crates/egui_demo_app/tests/test_demo_app.rs
+++ b/crates/egui_demo_app/tests/test_demo_app.rs
@@ -4,7 +4,10 @@ use egui_demo_app::{Anchor, WrapApp};
 use egui_kittest::SnapshotResults;
 use egui_kittest::kittest::Queryable as _;
 
-#[test]
+fn main() {
+    test_demo_app();
+}
+
 fn test_demo_app() {
     let mut harness = egui_kittest::Harness::builder()
         .with_size(Vec2::new(900.0, 600.0))
@@ -73,5 +76,8 @@ fn test_demo_app() {
         harness.run_steps(4);
 
         results.add(harness.try_snapshot(anchor.to_string()));
+
+        harness.spawn_eframe_app();
+        break;
     }
 }
```
2026-04-20 14:07:45 +02:00
Emil Ernerfeldt
1cd89b5edc Remove everything that was marked #[deprecated] (#8105)
Simplify. Streamline. Spring cleaning.
2026-04-14 20:19:36 +02:00
Michael Grupp
0435d2a9a1 Add HarnessBuilder::with_render_options() (closes #7630) (#8060)
Allows to override the default `PREDICTABLE` render options, e.g. if
it's desired to create snapshots with the exact texture options used by
the app.

See #7630 for details / examples.
2026-04-04 12:09:56 +02:00
Emil Ernerfeldt
4169d2c196 Enable more clippy lints (#7801) 2025-12-21 21:57:29 +01:00
Emil Ernerfeldt
7fe58bbfd4 Forbid uses of unwrap() in the code (#7795) 2025-12-19 20:34:18 +01:00
Emil Ernerfeldt
2f6fe9c572 eframe: Replace Frame::update with fn logic and fn ui (#7775)
* Part of https://github.com/emilk/egui/issues/5113
* Part of https://github.com/emilk/egui/issues/3524

## What
This deprecates `eframe::App::update` and replaces it with two new
functions:

```rs
pub trait App {
	/// Called just before `ui`, and in the future this will
    /// also be called for background apps when needed.
	fn logic(&mut self, ctx: &egui::Context, frame: &mut Frame) { }
	
    /// Show your user interface to the user.
	fn ui(&mut self, ui: &mut egui::Ui, frame: &mut Frame);

	…
}
```

Similarly, `Context::run` is deprecated in favor of `Context::run_ui`.

`Plugin`s are now handed a `Ui` instead of just a `Context` in
`on_begin/end_frame`.

## TODO
…either in this PR or a later one
* [x] Deprecate `App::update`
* [x] Deprecate `Context::run`
* [x] Change plugins to get a `Ui`
* [x] Update kittest
* [x] Change viewports to get UI:s (`show_viewport_immediate` etc)
  - https://github.com/emilk/egui/pull/7779

## Later PRs
* [ ] Deprecate `Panel::show`
* [ ] Deprecate `CentralPanel::show`
* [ ] Deprecate `CentralPanel` ?
2025-12-16 17:05:50 +01:00
Lucas Meurer
de907612b7 Enforce consistent snapshot updates (#7744)
* Closes https://github.com/emilk/egui/issues/7647


This collects SnapshotResults within the Harness and adds a check to
enforce snapshot results are merged in case multiple Harnesses are
constructed within a test.

This should make snapshot updates via kitdiff/accept_snapshots.sh way
more useful since it should now always update all snapshots instead of
only the first one per test.
2025-11-26 14:56:19 +01:00
Lucas Meurer
a19629ef4a Add kittest.toml config file (#7643)
* part of https://github.com/rerun-io/rerun/issues/10991

---------

Co-authored-by: lucasmerlin <8009393+lucasmerlin@users.noreply.github.com>
2025-11-25 14:51:18 +01:00
Emil Ernerfeldt
f74b7c7e79 Paint mouse cursor in kittest snapshot images (#7721)
Very simple triangle shape, but helps understand why a widget has a
hovered effect
2025-11-18 06:24:03 +01:00
Emil Ernerfeldt
d8dcb31673 kittest: add drag-and-drop helpers (#7690) 2025-11-07 14:46:09 +01:00
Emil Ernerfeldt
c79096ecc4 Add egui_kittest::Harness::set_options (#7638)
Makes it easier to set the same options for many tests

---------

Co-authored-by: Lucas Meurer <hi@lucasmerlin.me>
2025-10-15 11:42:52 +02:00
Lucas Meurer
da39198142 Some minor docs improvements (#7614) 2025-10-09 12:00:39 +02:00
Lucas Meurer
718a82b013 Harness: Add remove_cursor, event and event_modifiers (#7607)
* Closes https://github.com/emilk/egui/issues/7591
2025-10-08 13:47:00 +02:00
Gijs de Jong
48d903d879 Include popups and tooltips in Harness::fit_contents (#7556)
This makes `Harness::fit_contents` also use popups and tooltips to
compute the size of the contents.
2025-09-23 11:03:30 +02:00
Lucas Meurer
ea76b4eeca Add egui_kittest::HarnessBuilder::with_os and set the default to Nix (#7493)
Co-authored-by: Emil Ernerfeldt <emil.ernerfeldt@gmail.com>
2025-09-09 13:44:59 +02:00
Lucas Meurer
42c2fc58c9 Allow masking widgets in kittest snapshots (#7467)
* Closes <https://github.com/emilk/egui/issues/THE_RELEVANT_ISSUE>
* [ ] I have followed the instructions in the PR template
2025-08-21 17:46:36 +02:00
Lucas Meurer
6d312cc4c7 Add support for scrolling via accesskit / kittest (#7286)
I need to scroll in a snapshot test in my app, and kittest had no
utilities for this. Event::MouseWheel is error prone. This adds support
for some accesskit scroll actions, and uses this in kittest to add
helpers to scroll to a node / scroll the scroll area surrounding a node.

The accesskit code says down/up/left/right `Scrolls by approximately one
screen in a specific direction.`. Unfortunately it's difficult to get
the size of a "screen" (I guess that would be the size of the containing
scroll area)where I implemented the scrolling, so for now I've hardcoded
it to 100px. I think scrolling a fixed amount is still better than not
scrolling at all.

---------

Co-authored-by: Emil Ernerfeldt <emil.ernerfeldt@gmail.com>
2025-07-03 12:02:05 +02:00
Emil Ernerfeldt
22c6a9ae69 egui_kittest: Add HarnessBuilder::theme (#7289)
Makes it ergonomic to snapshot test light vs dark mode
2025-07-02 12:00:22 +02:00
Lucas Meurer
0152a87519 Create custom egui_kittest::Node (#7138)
This adds a custom Node struct with proper support for egui types
(`Key`, `Modifiers`, `egui::Event`, `Rect`) instead of needing to use
the kittest / accesskit types.

I also changed the `click` function to do a proper mouse move / mouse
down instead of the accesskit click. Also added `accesskit_click` to
trigger the accesskit event. This resulted in some changed snapshots,
since the elements are now hovered.

Also renamed `press_key` to `key_press` for consistency with
`key_down/key_up`.

Also removed the Deref to the AccessKit Node, to make it clearer when to
expect egui and when to expect accesskit types.

* Closes #5705 
* [x] I have followed the instructions in the PR template
2025-06-17 12:17:38 +02:00
Lucas Meurer
120d736cfc Add ImageLoader::has_pending and wait_for_pending_images (#7030)
With kittest it was difficult to wait for images to be loaded before
taking a snapshot test.
This PR adds `Harness::with_wait_for_pending_images` (true by default)
which will cause `Harness::run` to sleep until all images are loaded (or
`HarnessBuilder::with_max_steps` is exceeded).

It also adds a new ImageLoader::has_pending and
BytesLoader::has_pending, which should be implemented if things are
loaded / decoded asynchronously.

It reverts https://github.com/emilk/egui/pull/6901 which was my previous
attempt to fix this (but this didn't work since only the tested crate is
compiled with cfg(test) and not it's dependencies)
2025-05-08 09:27:52 +02:00
Lucas Meurer
501905b60d Add tests for layout and visuals of most egui widgets (#6752)
This is mostly in preparation for #5830 where I want to ensure that I
don't introduce any regressions
2025-04-16 18:58:58 +02:00
lucasmerlin
08c5a641a1 Run a frame per queued event in egui_kittest (#5704)
This should fix the remaining problems with the modifiers
* [x] I have followed the instructions in the PR template
2025-02-12 14:20:50 +01:00
lucasmerlin
1c6e7b1bd0 Fix modifiers not working in kittest (#5693)
* Closes <https://github.com/emilk/egui/issues/5690>
* [x] I have followed the instructions in the PR template

It still isn't ideal, since you have to remember to call key_up on a
separate frame.

---------

Co-authored-by: Emil Ernerfeldt <emil.ernerfeldt@gmail.com>
2025-02-10 09:33:36 +01:00
Andreas Reich
30e66e4575 Wgpu resources are no longer wrapped in Arc (since they are now Clone) (#5612)
Co-authored-by: Nicolas <bircni@icloud.com>
2025-01-20 18:06:35 +01:00
Emil Ernerfeldt
164f56f554 Fix some clippy issues found by 1.84.0 (#5603) 2025-01-13 08:29:13 +01:00
lucasmerlin
52060c0c41 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
2025-01-07 08:33:44 +01:00
lucasmerlin
46b58e5bcc Add Harness::new_eframe and TestRenderer trait (#5539)
Co-authored-by: Andreas Reich <r_andreas2@web.de>
2025-01-02 17:48:39 +01:00
lucasmerlin
e28505077d Update accesskit to 0.17 (#5372)
Updates accesskit and kittest. 

* [x] I have followed the instructions in the PR template
2024-11-26 15:16:08 +01:00
lucasmerlin
9ecc0b232c Fix disabled widgets "eating" focus (#5370)
- fixes https://github.com/emilk/egui/issues/5359

For the test I added a `Harness::press_key` function. We should
eventually add these to kittest, probably via a trait one can implement
for the `Harness` but for now this should do.
2024-11-26 14:31:30 +01:00
lucasmerlin
3c7ad0ee12 egui_kittest: Allow passing state to the app closure (#5313)
The allows us to pass any state to the ui closure. While it is possible
to just store state in the closure itself, accessing that state after
the harness was created to e.g. read or modify it would require interior
mutability. With this change there are new `Harness::new_state`,
`Harness::run_state`, ... methods that allow passing state on each run.

This builds on top of #5301, which should be merged first

---------

Co-authored-by: Emil Ernerfeldt <emil.ernerfeldt@gmail.com>
2024-11-06 14:43:41 +01:00
lucasmerlin
ad14bf2490 Add Harness::new_ui, Harness::fit_contents (#5301)
This adds a `Harness::new_ui`, which accepts a Ui closure and shows the
ui in a central panel. One big benefit is that this allows us to add a
fit_contents method that can run the ui closure with a sizing pass and
resize the "screen" based on the content size.

I also used this to add a snapshot test for the rendering_test at
different scales.
2024-11-01 18:30:40 +01:00
lucasmerlin
70a01138b7 Add egui testing library (#5166)
- closes #3491 
- closes #3926

This adds a testing library to egui based on
[kittest](https://github.com/rerun-io/kittest). Kittest is a new
[AccessKit](https://github.com/AccessKit/accesskit/)-based testing
library. The api is inspired by the js
[testing-library](https://testing-library.com/) where the idea is also
to query the dom based on accessibility attributes.
We made kittest with egui in mind but it should work with any rust gui
framework with AccessKit support.

It currently has support for:
- running the egui app, frame by frame
- building the AccessKit tree
- ergonomic queries via kittest
  - via e.g. get_by_name, get_by_role
- simulating events based on the accesskit node id
- creating arbitrary events based on Harness::input_mut
- rendering screenshots via wgpu
- snapshot tests with these screenshots

A simple test looks like this: 
```rust
fn main() {
    let mut checked = false;
    let app = |ctx: &Context| {
        CentralPanel::default().show(ctx, |ui| {
            ui.checkbox(&mut checked, "Check me!");
        });
    };

    let mut harness = Harness::builder().with_size(egui::Vec2::new(200.0, 100.0)).build(app);
    
    let checkbox = harness.get_by_name("Check me!");
    assert_eq!(checkbox.toggled(), Some(Toggled::False));
    checkbox.click();
    
    harness.run();

    let checkbox = harness.get_by_name("Check me!");
    assert_eq!(checkbox.toggled(), Some(Toggled::True));

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

~Since getting wgpu to run in ci is a hassle, I'm taking another shot at
creating a software renderer for egui (ideally without a huge dependency
like skia)~ (this didn't work as well as I hoped and it turns out in CI
you can just run tests on a mac runner which comes with a real GPU)
 
Here is a example of a failed snapshot test in ci, it will say which
snapshot failed and upload an artifact with the before / after and diff
images:

https://github.com/emilk/egui/actions/runs/11183049487/job/31090724606?pr=5166
2024-10-22 12:39:00 +02:00