Files
Brandon ThomasandClaude Opus 5.5 320e3a971a Fix up merged PRs: one Editing group on Home, fmt, docs after the format/canvas/dialog merges
- Home: #556's Find and Replace join main's Replace Fonts… in one Editing group with the
  Selection Pane, as PowerPoint lays it out; the separate group pushed Replace Fonts… out of
  reach at 1400 px. The Replace Fonts test picks the dialog's Replace button, not the ribbon's.
- cargo fmt.
- docs: parity summary regenerated with `cargo xtask parity`; ui-parity's ruler row says tab
  stops are set on the ruler (#567/#569) as well as in the Tabs dialog.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-14 15:04:16 -04:00

72 lines
2.7 KiB
Rust
Raw Permalink 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.
//! Home › Replace Fonts…: the dialog lists the deck's fonts and replaces one, as one undo step.
use deckcraft_engine::Session;
use egui_kittest::Harness;
use egui_kittest::kittest::Queryable;
use serde_json::json;
use crate::{Services, SlideApp};
fn harness() -> Harness<'static, SlideApp> {
let mut s = Session::with_new();
s.execute("slide.new", &json!({"layout": "blank"})).unwrap();
s.execute("insert.textBox", &json!({"rect": [40, 40, 400, 80], "text": "Hello fonts"})).unwrap();
s.execute("text.exit", &json!({})).unwrap();
s.execute("format.font", &json!({"family": "Comic Neue"})).unwrap();
s.execute("format.size", &json!({"size": 40})).unwrap();
let app = SlideApp::new(s, Services::default());
let mut h = Harness::builder().with_size(egui::vec2(1400.0, 900.0)).with_step_dt(1.0 / 60.0).build_ui_state(
|ui, app: &mut SlideApp| {
app.logic(ui.ctx());
app.ui(ui);
},
app,
);
h.run_steps(3);
h
}
fn run_font(h: &Harness<'_, SlideApp>) -> Option<String> {
let st = h.state().session.active().unwrap();
st.current_slide()
.unwrap()
.shapes
.iter()
.find_map(|s| s.text.as_ref())
.and_then(|b| b.paragraphs.first())
.and_then(|p| p.runs.first())
.and_then(|r| r.props.font.clone())
}
#[test]
fn ribbon_button_opens_the_dialog_and_replaces() {
let mut h = harness();
h.get_by_label("Replace Fonts…").click();
h.run_steps(3);
assert_eq!(h.state().dialog.as_ref().map(|d| d.id.as_str()), Some("replaceFonts"));
// Pick the font to replace and type the new one, the way a person would.
if let Some(d) = h.state_mut().dialog.as_mut() {
d.fields.insert("from".into(), "Comic Neue".into());
d.fields.insert("to".into(), "Lato".into());
}
h.run_steps(2);
// The ribbon has a Replace button too (Find and Replace); the dialog's is drawn last.
h.query_all_by_label("Replace").last().expect("the dialog's Replace button").click();
h.run_steps(3);
assert_eq!(run_font(&h).as_deref(), Some("Lato"));
// The dialog stays open with a confirmation, like PowerPoint's.
assert!(h.query_by_label_contains("Replaced “Comic Neue”").is_some());
h.state_mut().session.execute("edit.undo", &json!({})).unwrap();
assert_eq!(run_font(&h).as_deref(), Some("Comic Neue"));
}
#[test]
#[ignore = "writes a screenshot for review"]
fn screenshot() {
let mut h = harness();
h.render().unwrap().save("/tmp/replacefonts0.png").unwrap();
h.state_mut().dialog = Some(crate::dialogs::Dialog::new("replaceFonts"));
h.run_steps(4);
h.render().unwrap().save("/tmp/replacefonts.png").unwrap();
}