diff --git a/Cargo.lock b/Cargo.lock index 6121aa34..8d5913da 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1422,7 +1422,9 @@ dependencies = [ "egui_extras", "image", "kittest", + "open", "pollster", + "tempfile", "wgpu", ] @@ -2318,6 +2320,15 @@ dependencies = [ "hashbrown 0.15.2", ] +[[package]] +name = "is-docker" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "928bae27f42bc99b60d9ac7334e3a21d10ad8f1835a4e12ec3ec0464765ed1b3" +dependencies = [ + "once_cell", +] + [[package]] name = "is-terminal" version = "0.4.13" @@ -2329,6 +2340,16 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "is-wsl" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "173609498df190136aa7dea1a91db051746d339e18476eed5ca40521f02d7aa5" +dependencies = [ + "is-docker", + "once_cell", +] + [[package]] name = "itertools" version = "0.10.5" @@ -3065,6 +3086,17 @@ version = "11.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b410bbe7e14ab526a0e86877eb47c6996a2bd7746f027ba551028c925390e4e9" +[[package]] +name = "open" +version = "5.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2483562e62ea94312f3576a7aca397306df7990b8d89033e18766744377ef95" +dependencies = [ + "is-wsl", + "libc", + "pathdiff", +] + [[package]] name = "option-ext" version = "0.2.0" @@ -3143,6 +3175,12 @@ version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" +[[package]] +name = "pathdiff" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df94ce210e5bc13cb6651479fa48d14f601d9858cfe0467f43ae157023b938d3" + [[package]] name = "percent-encoding" version = "2.3.1" @@ -4064,15 +4102,15 @@ dependencies = [ [[package]] name = "tempfile" -version = "3.13.0" +version = "3.23.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0f2c9fc62d0beef6951ccffd757e241266a2c833136efbe35af6cd2567dca5b" +checksum = "2d31c77bdf42a745371d260a26ca7163f1e0924b64afa0b688e61b5a9fa02f16" dependencies = [ - "cfg-if", "fastrand", + "getrandom 0.3.1", "once_cell", - "rustix 0.38.38", - "windows-sys 0.59.0", + "rustix 1.0.8", + "windows-sys 0.60.2", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index c3a1195d..52dad4fa 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -95,6 +95,7 @@ objc2 = "0.5.1" objc2-app-kit = { version = "0.2.0", default-features = false } objc2-foundation = { version = "0.2.0", default-features = false } objc2-ui-kit = { version = "0.2.0", default-features = false } +open = "5" parking_lot = "0.12" percent-encoding = "2.1" pollster = "0.4" @@ -107,6 +108,7 @@ serde = { version = "1", features = ["derive"] } similar-asserts = "1.4.2" smallvec = "1" static_assertions = "1.1.0" +tempfile = "3" thiserror = "1.0.37" type-map = "0.5.0" unicode-segmentation = "1.12.0" @@ -114,7 +116,7 @@ wasm-bindgen = "0.2" wasm-bindgen-futures = "0.4" web-sys = "0.3.73" web-time = "1.1.0" # Timekeeping for native and web -wgpu = { version = "27.0.0", default-features = false } +wgpu = { version = "27.0.0", default-features = false, features = ["std"] } windows-sys = "0.60" winit = { version = "0.30.12", default-features = false } diff --git a/clippy.toml b/clippy.toml index 839586db..9ce15103 100644 --- a/clippy.toml +++ b/clippy.toml @@ -39,7 +39,7 @@ disallowed-methods = [ # but we cannot disable them all here (because of e.g. https://github.com/rust-lang/rust-clippy/issues/10406) # so we do that in `clipppy_wasm.toml` instead. - { path = "std::env::temp_dir", readon = "Use the tempdir crate instead" }, + { path = "std::env::temp_dir", readon = "Use the tempfile crate instead" }, { path = "std::panic::catch_unwind", reason = "We compile with `panic = abort" }, { path = "std::thread::spawn", readon = "Use `std::thread::Builder` and name the thread" }, ] diff --git a/crates/egui_kittest/Cargo.toml b/crates/egui_kittest/Cargo.toml index 19340fdd..adb955e9 100644 --- a/crates/egui_kittest/Cargo.toml +++ b/crates/egui_kittest/Cargo.toml @@ -33,7 +33,7 @@ wgpu = [ ] ## Adds a dify-based image snapshot utility. -snapshot = ["dep:dify", "dep:image", "image/png"] +snapshot = ["dep:dify", "dep:image", "dep:open", "dep:tempfile", "image/png"] ## Allows testing eframe::App eframe = ["dep:eframe", "eframe/accesskit"] @@ -61,6 +61,8 @@ wgpu = { workspace = true, features = [ # snapshot dependencies dify = { workspace = true, optional = true } +open = { workspace = true, optional = true } +tempfile = { workspace = true, optional = true } # Enable this when generating docs. document-features = { workspace = true, optional = true } diff --git a/crates/egui_kittest/src/snapshot.rs b/crates/egui_kittest/src/snapshot.rs index da00795f..7e171346 100644 --- a/crates/egui_kittest/src/snapshot.rs +++ b/crates/egui_kittest/src/snapshot.rs @@ -544,7 +544,7 @@ pub fn image_snapshot(current: &image::RgbaImage, name: impl Into) { } } -#[cfg(feature = "wgpu")] +#[cfg(any(feature = "wgpu", feature = "snapshot"))] impl Harness<'_, State> { /// Render an image using the setup [`crate::TestRenderer`] and compare it to the snapshot /// with custom options. @@ -635,6 +635,49 @@ impl Harness<'_, State> { } } } + + /// Render a snapshot, save it to a temp file and open it in the default image viewer. + /// + /// This method is marked as deprecated to trigger errors in CI (so that it's not accidentally + /// committed). + #[deprecated = "Only for debugging, don't commit this."] + pub fn debug_open_snapshot(&mut self) { + let image = self + .render() + .map_err(|err| SnapshotError::RenderError { err }) + .unwrap(); + let temp_file = tempfile::Builder::new() + .disable_cleanup(true) // we keep the file so it's accessible even after the test ends + .prefix("kittest-snapshot") + .suffix(".png") + .tempfile() + .expect("Failed to create temp file"); + + let path = temp_file.path(); + + image + .save(temp_file.path()) + .map_err(|err| SnapshotError::WriteSnapshot { + err, + path: path.to_path_buf(), + }) + .unwrap(); + + #[expect(clippy::print_stdout)] + { + println!("Wrote debug snapshot to: {}", path.display()); + } + let result = open::that(path); + if let Err(err) = result { + #[expect(clippy::print_stderr)] + { + eprintln!( + "Failed to open image {} in default image viewer: {err}", + path.display() + ); + } + } + } } /// Utility to collect snapshot errors and display them at the end of the test. diff --git a/deny.toml b/deny.toml index 30593286..5d789448 100644 --- a/deny.toml +++ b/deny.toml @@ -48,13 +48,14 @@ skip = [ { name = "bit-set" }, # wgpu's naga depends on 0.8, syntect's (used by egui_extras) fancy-regex depends on 0.5 { name = "bit-vec" }, # dependency of bit-set in turn, different between 0.6 and 0.5 { name = "bitflags" }, # old 1.0 version via glutin, png, spirv, … + { name = "core-foundation" }, # version conflict between winit and wgpu ecosystems + { name = "core-graphics-types" }, # version conflict between winit and wgpu ecosystems + { name = "getrandom" }, # ring / rustls (and thus ehttp) still depend on getrandom 0.2 { name = "quick-xml" }, # old version via wayland-scanner { name = "redox_syscall" }, # old version via winit { name = "thiserror" }, # ecosystem is in the process of migrating from 1.x to 2.x { name = "thiserror-impl" }, # same as above { name = "windows-sys" }, # mostly hopeless to avoid - { name = "core-foundation" }, # version conflict between winit and wgpu ecosystems - { name = "core-graphics-types" }, # version conflict between winit and wgpu ecosystems ] skip-tree = [ { name = "hashbrown" }, # wgpu's naga depends on 0.16, accesskit depends on 0.15