mirror of
https://github.com/storytold/pdfcraft.git
synced 2026-10-24 01:57:12 -06:00
* #2028: test that Edit text & images is the first Modify page item Edit text & images was listed under Add content, though it changes what is already on the page. The test checks that the Edit a PDF catalogue lists it first under Modify page and not under Add content. With the item back under Add content it fails on the section assertion (left: Add content, right: Modify page). * #246: test that start-up and the panic hook never use eprintln eprintln! panics when standard error is a broken pipe, and a panic inside the panic hook aborts the process. The test scans the product code of the desktop main.rs (everything before the test module) and fails on any eprintln! outside a comment. With the old eprintln! calls restored in the panic hook and the log-file warning, it fails listing main.rs:188 and main.rs:227. * #843: test that text typed into an open paragraph counts as unsaved work An open paragraph with a draft that was not applied yet was not counted as unsaved work, so closing the tab or quitting skipped the save prompt. The test opens a paragraph, types into it, and checks that first_dirty() reports the tab (and not before typing, nor after the original text is typed back). Without the line_editor check in has_unsaved_work, first_dirty() stays None and the assertion fails (left: None, right: Some(0)).
This commit is contained in:
@@ -1414,4 +1414,26 @@ mod tests {
|
||||
let class = entry.lines().find_map(|line| line.strip_prefix("StartupWMClass="));
|
||||
assert_eq!(class, Some(super::APP_ID));
|
||||
}
|
||||
|
||||
// Regression test for #246: `eprintln!` panics when standard error is a broken pipe (a GUI
|
||||
// launch on Windows), and a panic inside the panic hook aborts the process. The start-up
|
||||
// path and the hook must write to standard error without it.
|
||||
#[test]
|
||||
fn start_up_and_the_panic_hook_never_use_eprintln() {
|
||||
let source = include_str!("main.rs");
|
||||
// Everything before the top-level test module is product code.
|
||||
let product = source.split("\n#[cfg(test)]\nmod tests {").next().unwrap_or(source);
|
||||
assert!(product.len() < source.len(), "found the end of the product code");
|
||||
let offenders: Vec<_> = product
|
||||
.lines()
|
||||
.enumerate()
|
||||
.filter(|(_, line)| !line.trim_start().starts_with("//") && line.contains("eprintln!"))
|
||||
.map(|(n, line)| format!("main.rs:{}: {}", n + 1, line.trim()))
|
||||
.collect();
|
||||
assert!(
|
||||
offenders.is_empty(),
|
||||
"`eprintln!` panics on a broken standard error pipe; use `log::warn!` or `write_fmt` on `stderr()` and ignore the error:\n{}",
|
||||
offenders.join("\n")
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -596,6 +596,19 @@ mod tests {
|
||||
assert!(menus >= 3);
|
||||
}
|
||||
|
||||
// Regression test for #2028: Edit text & images sat under "Add content", though it changes
|
||||
// what is already on the page; it belongs first under "Modify page".
|
||||
#[test]
|
||||
fn edit_text_and_images_is_the_first_item_under_modify_page() {
|
||||
let edit = group("edit").expect("the Edit a PDF tool");
|
||||
let section_of = |command: &str| edit.sections.iter().find(|s| s.items.iter().any(|i| i.command == command)).map(|s| s.title);
|
||||
assert_eq!(section_of("edit.edit_text"), Some("Modify page"), "Edit text & images is a Modify page tool");
|
||||
let modify = edit.sections.iter().find(|s| s.title == "Modify page").expect("a Modify page section");
|
||||
assert_eq!(modify.items.first().map(|i| i.command), Some("edit.edit_text"), "and the first one, so it is not below the fold");
|
||||
let add = edit.sections.iter().find(|s| s.title == "Add content").expect("an Add content section");
|
||||
assert!(add.items.iter().all(|i| i.command != "edit.edit_text"), "it adds nothing, so it is not listed under Add content");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn every_update_and_remove_command_is_reachable_from_a_tool_entry() {
|
||||
let reachable: HashSet<&str> =
|
||||
|
||||
@@ -3090,6 +3090,45 @@ fn switching_straight_to_another_box_applies_the_open_paragraph() {
|
||||
assert_eq!(ed.text, "Bottom");
|
||||
}
|
||||
|
||||
// Regression test for #811: text typed into an open paragraph was not counted as unsaved work, so
|
||||
// closing the tab or quitting discarded it without the save prompt.
|
||||
#[test]
|
||||
fn text_typed_into_an_open_paragraph_counts_as_unsaved_work() {
|
||||
let bytes = source_font_fixture_with_text("BT /F1 24 Tf 20 220 Td (Top) Tj ET");
|
||||
let mut h = Harness::builder().with_size(egui::vec2(1400.0, 900.0)).build_eframe(move |_cc| {
|
||||
let mut app = PdfCraftApp::new();
|
||||
app.set_option("language", "en").unwrap();
|
||||
app.open_bytes("box.pdf", None, bytes).expect("opens");
|
||||
app
|
||||
});
|
||||
h.run_steps(4);
|
||||
assert!(h.state_mut().execute("edit.edit_text"));
|
||||
h.run_steps(2);
|
||||
let r = h.state().views[0].page_screen_rect(0).expect("on screen");
|
||||
let k = r.width() / 300.0;
|
||||
let block = {
|
||||
let s = h.state();
|
||||
s.session.get(s.views[0].id).unwrap().text_blocks(0).into_iter().next().expect("one editable box")
|
||||
};
|
||||
let center = egui::pos2(
|
||||
r.left() + ((block.rect[0] + block.rect[2]) / 2.0) as f32 * k,
|
||||
r.top() + (300.0 - (block.rect[1] + block.rect[3]) / 2.0) as f32 * k,
|
||||
);
|
||||
click_at(&mut h, center);
|
||||
assert_eq!(h.state().views[0].line_editor.as_ref().map(|e| e.text.as_str()), Some("Top"), "the paragraph is open for typing");
|
||||
assert_eq!(h.state().first_dirty(), None, "opening a paragraph changes nothing");
|
||||
|
||||
h.state_mut().views[0].line_editor.as_mut().unwrap().text = "Top, and a draft not applied yet".into();
|
||||
h.run_steps(1);
|
||||
assert!(!h.state().session.get(h.state().views[0].id).unwrap().dirty, "the document itself is untouched until the draft is applied");
|
||||
assert_eq!(h.state().first_dirty(), Some(0), "the draft in the open paragraph is unsaved work");
|
||||
|
||||
// Typing the original text back leaves nothing to lose.
|
||||
h.state_mut().views[0].line_editor.as_mut().unwrap().text = "Top".into();
|
||||
h.run_steps(1);
|
||||
assert_eq!(h.state().first_dirty(), None, "a draft equal to the page text is not unsaved work");
|
||||
}
|
||||
|
||||
/// Dark pixels in `r`: glyph ink on a white page.
|
||||
fn ink(pixels: &image::RgbaImage, r: egui::Rect) -> usize {
|
||||
let (x0, y0, x1, y1) = (r.left().max(0.0) as u32, r.top().max(0.0) as u32, r.right() as u32, r.bottom() as u32);
|
||||
|
||||
Reference in New Issue
Block a user