Files
deckcraft/crates/ui-egui/src/slide_size_tests.rs
T
Nikita RakitinandCursor 22074c4c69 Format: repair degenerate slide sizes on load
repair() brings each slide side into PowerPoint's 72–4032 pt (as Design › Slide Size allows;
it accepted 1–4000 before), and replaces a zero, negative or non-finite size with 16:9; a bad
notes size gets the default. The native reader takes a null, string or missing slide/notes
size as NaN for repair to fix, so such a file opens instead of failing as damaged (NaN and
infinity are saved as null). The canvas fit and slide show fit treat a zero or non-finite side
as 1 pt, so an in-memory bad size can't make layout infinite.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-10-14 04:35:13 +03:00

59 lines
2.8 KiB
Rust
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
//! Slide sizes at the edges of what a loaded file can give (after `deckcraft_format::repair`):
//! the editor, sorter, slide show and presenter view open without panicking. (NaN and infinity
//! are saved as null, which used to make the file fail to open.)
#![allow(clippy::unwrap_used, clippy::expect_used)]
use serde_json::json;
use crate::{Services, SlideApp};
use deckcraft_engine::Session;
fn open_with_size(w: f64, h: f64) -> egui_kittest::Harness<'static, SlideApp> {
// Written with the size, then opened the way File › Open does (load, then repair).
let mut s = Session::with_new();
s.execute("slide.new", &json!({})).unwrap();
std::sync::Arc::make_mut(&mut s.active_mut().unwrap().doc).slide_size = deckcraft_model::Size::new(w, h);
let path = std::env::temp_dir().join(format!("deckcraft-size-{}-{w}x{h}.deckcraft", std::process::id()));
s.execute("file.saveAs", &json!({"path": path.to_string_lossy()})).unwrap();
let mut s = Session::new();
s.execute("file.open", &json!({"path": path.to_string_lossy()})).unwrap();
let _ = std::fs::remove_file(&path);
egui_kittest::Harness::builder().with_size(egui::vec2(1280.0, 800.0)).build_ui_state(
|ui, app: &mut SlideApp| {
app.logic(ui.ctx());
app.ui(ui);
},
SlideApp::new(s, Services::default()),
)
}
#[test]
fn extreme_loaded_slide_sizes_open_in_every_view() {
for (w, h) in [(0.0, 0.0), (-5.0, 540.0), (f64::NAN, 540.0), (f64::INFINITY, 1.0), (1.0, 1.0), (1e9, 1e9), (4000.0, 4000.0)] {
let mut hs = open_with_size(w, h);
hs.run_steps(3);
let size = hs.state().session.active().unwrap().doc.slide_size;
assert!((72.0..=4032.0).contains(&size.width) && (72.0..=4032.0).contains(&size.height), "{w}x{h}: {size:?}");
for cmd in ["view.sorter", "view.normal"] {
hs.state_mut().run(cmd, json!({})).unwrap();
hs.run_steps(2);
}
hs.state_mut().run("show.presenter", json!({"on": true})).unwrap();
hs.state_mut().run("show.start", json!({"from": 0})).unwrap();
hs.run_steps(3);
assert!(hs.state().show.is_some(), "{w}x{h}");
}
}
/// A presentation whose size went bad in memory (not through a file) still lays out: the
/// canvas fit stays finite and positive.
#[test]
fn the_canvas_fit_survives_a_zero_slide_size_in_memory() {
let mut s = Session::with_new();
std::sync::Arc::make_mut(&mut s.active_mut().unwrap().doc).slide_size = deckcraft_model::Size::new(0.0, f64::NAN);
let app = SlideApp::new(s, Services::default());
let (r, scale) = crate::canvas::layout(&app, egui::Rect::from_min_size(egui::Pos2::ZERO, egui::vec2(1000.0, 700.0)));
assert!(scale.is_finite() && scale > 0.0, "{scale}");
assert!(r.min.x.is_finite() && r.max.y.is_finite(), "{r:?}");
}