Tests: the Options dialog's Cancel, Esc and the close button restore the settings (#878)

The Options dialog applies every change as it is made, and closing it
with Cancel, Esc or the window's close button puts the settings back the
way they were. Nothing covered that, so a change to the dialog could have
dropped it unnoticed.

The kittest now covers all three ways out: a checkbox put back by Cancel,
the appearance and the interface size put back by Esc, the same checkbox
put back by the window's close button, and the dialog closing in each
case. Red-proof: with the Cancel restore removed the checkbox test fails
(the setting stays changed), with the Esc restore removed the appearance
test fails (it stays dark), and with the Esc/close restore removed the
close-button test fails (the setting stays changed).

ROADMAP progress-log row added.
This commit is contained in:
Sazid Al Bayazid
2026-10-20 09:21:26 +06:00
parent f34f4121c8
commit 0b476e823d
3 changed files with 100 additions and 0 deletions
+1
View File
@@ -137,6 +137,7 @@ app's JSON control channel (`deckcraft --control PORT`).
| 2026-10-17 | Edit Points: turning a shape into a freeform is one undo step, so Undo brings the original shape back (it used to stay a freeform) |
| 2026-10-17 | While a placeholder's text is being edited, a click on a shape in front of it selects that shape instead of moving the caret, as in PowerPoint (#931) |
| 2026-10-15 | Native saves keep an imported chart's embedded workbook, drawings and relationships; headless PPTX → edit → native save/reopen → PPTX tests verify the payloads and stale-workbook rejection |
| 2026-10-20 | Tests: the Options dialog's Cancel, Esc and close button put the settings back the way they were (#878) |
| 2026-10-15 | PPTX trigger sequences keep separate On Click steps, including paragraph builds; synthetic import/edit/save/reopen and headless show regressions |
| 2026-10-16 | Export: PNG with a transparent background — the slide background is left out, only the slide's content is drawn (Export… dialog, File › Export, web download, `file.export`/`file.render` `transparentBackground`, `deckcraft-cli render --transparent`) (#784) |
| 2026-10-16 | Arrange ▸ Align: Align to Slide and Align Selected Objects, as in PowerPoint. One object aligns to the slide and several to each other until the other choice is ticked; the choice holds for that selection and also drives Distribute |
+4
View File
@@ -3684,3 +3684,7 @@ mod spelling_tests;
#[cfg(test)]
#[path = "paragraph_dialog_tests.rs"]
mod paragraph_dialog_tests;
#[cfg(test)]
#[path = "preferences_tests.rs"]
mod preferences_tests;
+95
View File
@@ -0,0 +1,95 @@
//! The Preferences (Options) dialog: controls apply as they change and Cancel, Esc and the
//! window's close button put the settings back the way they were (#752, reported as #878).
use deckcraft_engine::Session;
use egui_kittest::kittest::{NodeT, Queryable};
use egui_kittest::{Harness, Node};
use serde_json::json;
use crate::theme::Brightness;
use crate::{Services, SlideApp};
/// The slider itself, not the label drawn beside it.
fn interface_size<'a>(h: &'a Harness<'_, SlideApp>) -> Node<'a> {
h.get_all_by_label("Interface size").find(|n| n.accesskit_node().role() == egui::accesskit::Role::Slider).expect("the slider is there")
}
fn harness() -> Harness<'static, SlideApp> {
let mut h = Harness::builder().with_size(egui::vec2(1400.0, 900.0)).build_ui_state(
|ui, app: &mut SlideApp| {
app.logic(ui.ctx());
app.ui(ui);
},
SlideApp::new(Session::with_new(), Services::default()),
);
// The app keeps asking for frames, so step instead of run().
h.run_steps(3);
h
}
fn open_options(h: &mut Harness<'_, SlideApp>) {
h.state_mut().run("app.preferences", json!({})).expect("open Options");
h.run_steps(3);
}
fn dark(app: &SlideApp) -> bool {
app.ui.brightness == Brightness::Dark
}
/// A checkbox applies as it is toggled and Cancel puts the old value back.
#[test]
fn options_cancel_undoes_the_changes() {
let mut h = harness();
let was = h.state().session.prefs.smart_guides;
open_options(&mut h);
h.query_by_label("Show smart guides").expect("the checkbox is there").click();
h.run_steps(2);
assert_eq!(h.state().session.prefs.smart_guides, !was, "the change applies as it is made");
h.query_by_label("Cancel").expect("the Cancel button is there").click();
h.run_steps(2);
assert_eq!(h.state().session.prefs.smart_guides, was, "Cancel restores the setting");
assert!(h.state().dialog.is_none(), "and the dialog closes");
}
/// The appearance toggle and the interface size go back on Cancel, too; Esc acts as Cancel.
#[test]
fn options_cancel_puts_the_appearance_and_scale_back() {
let mut h = harness();
let (dark_before, scale_before) = (dark(h.state()), h.state().ui.ui_scale);
open_options(&mut h);
h.query_by_label("Dark appearance").expect("the checkbox is there").click();
h.run_steps(2);
assert!(dark(h.state()), "the appearance applies as it is toggled");
// Clicking the slider's middle sets it near the middle of its range, away from the default.
interface_size(&h).click();
h.run_steps(2);
let scale_in_dialog = h.state().ui.ui_scale;
assert!((scale_in_dialog - scale_before).abs() > 1e-3, "the slider applied a new size");
h.key_press(egui::Key::Escape);
h.run_steps(2);
assert_eq!(dark(h.state()), dark_before, "Esc restores the appearance");
assert!((h.state().ui.ui_scale - scale_before).abs() < 1e-3, "Esc restores the size");
assert!(h.state().dialog.is_none(), "and the dialog closes");
}
/// The window's close button is the same as Cancel: the settings go back.
#[test]
fn options_close_button_restores_the_settings() {
let mut h = harness();
let was = h.state().session.prefs.smart_guides;
open_options(&mut h);
h.query_by_label("Show smart guides").expect("the checkbox is there").click();
h.run_steps(2);
assert_eq!(h.state().session.prefs.smart_guides, !was, "the change applies as it is made");
h.get_all_by_label("Close window").next().expect("the window's close button is there").click();
h.run_steps(2);
assert_eq!(h.state().session.prefs.smart_guides, was, "the close button restores the setting");
assert!(h.state().dialog.is_none(), "and the dialog closes");
}