Files
pdfcraft/crates/ui-egui/tests/it/preferences_layout.rs
T
Lucas Sampaio Dias 03996b1025 Improve reading-colour preferences and add a settings shortcut (#2627)
* M3: improve reading-colour preferences and add settings shortcut

* M3: clarify the disabled reading-colour preview

* M3: adapt rebased preferences to current UI dependencies
2026-10-28 17:41:29 -04:00

105 lines
5.0 KiB
Rust

//! The Preferences dialog keeps OK in reach in a short window (#3557): the settings scroll, the
//! OK row does not.
use egui::Rect;
use egui_kittest::Harness;
use egui_kittest::kittest::Queryable;
use pdfcraft_ui_egui::PdfCraftApp;
fn harness(height: f32) -> Harness<'static, PdfCraftApp> {
let mut h = Harness::builder().with_size(egui::vec2(1000.0, height)).build_eframe(|_cc| {
let mut app = PdfCraftApp::new();
app.set_option("language", "en").unwrap();
app.set_option("dialog", "preferences").unwrap();
app
});
h.run_steps(6);
h
}
fn on_screen(rect: Rect, height: f32) -> bool {
rect.min.x >= 0.0 && rect.min.y >= 0.0 && rect.max.x <= 1000.0 && rect.max.y <= height
}
#[test]
fn ok_is_on_screen_without_scrolling_at_any_window_height() {
// From a short laptop window to a tall monitor, the settings never fit the short ones. 173 is
// the smallest window (520 pt) at the largest interface size (300%), 208 is 250%.
for height in [173.0, 208.0, 260.0, 420.0, 480.0, 560.0, 700.0, 900.0, 1100.0] {
let h = harness(height);
let ok = h.get_by_label("OK").rect();
assert!(on_screen(ok, height), "{height}: OK at {ok:?} is off the {height} pt window");
let title = h.get_by(|n| n.role() == egui::accesskit::Role::Label && n.value().as_deref() == Some("Preferences")).rect();
assert!(on_screen(title, height), "{height}: the title at {title:?} is off the window");
// The OK row sits below the scrolled settings, never over them: the settings' last visible
// row ends above it. The title is above everything.
assert!(title.max.y < ok.min.y, "{height}: title {title:?} above OK {ok:?}");
}
}
#[test]
fn ok_closes_the_dialog_in_a_short_window_and_the_settings_still_scroll() {
let mut h = harness(480.0);
// A setting far down the list starts out below the visible settings; scrolling brings it in
// between the title and the OK row, and OK did not move.
let ok_before = h.get_by_label("OK").rect();
let title = h.get_by(|n| n.role() == egui::accesskit::Role::Label && n.value().as_deref() == Some("Preferences")).rect();
let far = h.get_by_label_contains("Enable Acrobat JavaScript").rect();
assert!(far.min.y >= ok_before.min.y, "JavaScript setting starts out of sight: {far:?} vs OK {ok_before:?}");
h.get_by_label_contains("Enable Acrobat JavaScript").scroll_to_me();
h.run_steps(4);
let far = h.get_by_label_contains("Enable Acrobat JavaScript").rect();
assert!(far.min.y >= title.max.y && far.max.y <= ok_before.min.y, "JavaScript setting scrolled in between the title and OK: {far:?}");
assert_eq!(h.get_by_label("OK").rect(), ok_before, "OK stays put while the settings scroll");
assert!(h.state().dialog.is_some());
h.get_by_label("OK").click();
h.run_steps(3);
assert!(h.state().dialog.is_none(), "OK closes Preferences");
}
#[test]
fn the_dialog_opens_at_its_full_size_and_does_not_grow_afterwards() {
// With OK outside the scroll, the scroll area started from what the modal offered, which
// grew some 45 pt a frame for ten frames: the dialog opened small and stretched, and clicks
// in its first frames landed on controls that were still moving.
for height in [260.0, 560.0, 900.0] {
let mut h = harness(height);
let settled = (
h.get_by(|n| n.role() == egui::accesskit::Role::Label && n.value().as_deref() == Some("Preferences")).rect(),
h.get_by_label("OK").rect(),
);
h.run_steps(8);
let later = (
h.get_by(|n| n.role() == egui::accesskit::Role::Label && n.value().as_deref() == Some("Preferences")).rect(),
h.get_by_label("OK").rect(),
);
assert_eq!(settled, later, "{height}: the dialog moved after it had been shown for six frames");
}
// And it is in place within a few frames of opening, for the first click: a frame or two of
// settling is fine, ten frames of stretching is not.
let mut h = Harness::builder().with_size(egui::vec2(1400.0, 900.0)).build_eframe(|_cc| {
let mut app = PdfCraftApp::new();
app.set_option("language", "en").unwrap();
app
});
h.run_steps(4);
h.state_mut().dialog = Some(pdfcraft_ui_egui::Dialog::Preferences);
h.run_steps(3);
let early = h.get_by_label("Right").rect();
h.run_steps(8);
let late = h.get_by_label("Right").rect();
assert!((early.min.y - late.min.y).abs() <= 2.0 && (early.min.x - late.min.x).abs() <= 2.0, "{early:?} then {late:?}");
}
#[test]
fn a_very_tall_window_does_not_leave_a_blank_gap_above_ok() {
// The settings are some 1 400 pt tall; in a taller window the scroll area is not stretched
// past them.
let mut h = harness(2600.0);
h.run_steps(6);
let ok = h.get_by_label("OK").rect();
let last = h.get_by_label_contains("Enable Acrobat JavaScript").rect();
assert!(on_screen(ok, 2600.0) && on_screen(last, 2600.0), "{last:?} {ok:?}");
assert!(ok.min.y - last.max.y < 120.0, "a gap of {} pt between the last setting and OK", ok.min.y - last.max.y);
}