M10: Test current-page print previews and saved output (#1415)

Extend the coverage of #1411 with preview raster selection and a dialog-driven PDF save test. Reopen and render the saved PDF to verify the viewed physical page when labels restart. Cover duplicate labels and selection guards without changing production code.

Refs #1308, #1411

Co-authored-by: LabDennis <341377186+LabDennis@users.noreply.github.com>
This commit is contained in:
LabDennis 2026-10-12 14:37:11 +02:00 committed by GitHub
parent 2839152af1
commit 291d738160
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 90 additions and 0 deletions

View File

@ -1028,6 +1028,34 @@ pub(crate) fn body(
mod tests {
use super::*;
#[test]
fn current_page_preview_uses_positions_and_selection_guards() {
for labels in [["i", "ii", "iii", "1", "2"], ["1", "1", "1", "1", "1"], ["1", "2", "3", "4", "5"]] {
let labels: Vec<String> = labels.into_iter().map(str::to_owned).collect();
for current_page in 0..5 {
let draft = PrintDraft { which: Which::Current, current_page, ..Default::default() };
let rasters = preview_rasters(&draft, &[(200.0, 300.0); 5], &labels, 1.0, 8192.0);
assert_eq!(rasters.iter().map(|(page, _)| *page).collect::<Vec<_>>(), vec![current_page]);
}
}
let labels: Vec<String> = ["i", "ii", "iii", "1", "2"].into_iter().map(str::to_owned).collect();
let mut draft = PrintDraft { which: Which::Selected, selected: vec![0, 3], ..Default::default() };
assert_eq!(draft.settings(5, &labels).unwrap().pages, vec![0, 3]);
draft.which = Which::All;
assert_eq!(draft.settings(5, &labels).unwrap().pages, vec![0, 1, 2, 3, 4]);
draft.which = Which::Current;
draft.reverse = true;
draft.subset = Subset::Odd;
assert_eq!(draft.settings(5, &labels).unwrap().pages, vec![0]);
draft.subset = Subset::Even;
assert!(draft.settings(5, &labels).is_err());
draft.subset = Subset::All;
for (count, current) in [(0, 0), (5, 5), (5, usize::MAX)] {
draft.current_page = current;
assert!(draft.settings(count, &labels).is_err());
}
}
#[test]
fn composed_sheets_keep_exact_scaling_and_the_dialogs_duplex_choice() {
let draft = PrintDraft { duplex: spool::Duplex::LongEdge, ..PrintDraft::default() };

View File

@ -15,6 +15,68 @@ fn harness() -> Harness<'static, PdfCraftApp> {
h
}
#[test]
fn current_print_page_saves_the_viewed_page_when_labels_restart() {
// Five distinct painted pages, labelled i, ii, iii, 1, 2.
let mut objects = vec![
"<< /Type /Catalog /Pages 2 0 R /PageLabels << /Nums [0 << /S /r >> 3 << /S /D /St 1 >>] >> >>".to_owned(),
"<< /Type /Pages /Kids [3 0 R 5 0 R 7 0 R 9 0 R 11 0 R] /Count 5 /MediaBox [0 0 200 300] >>".to_owned(),
];
for (i, color) in ["1 0 0", "0 1 0", "0 0 1", "1 1 0", "1 0 1"].iter().enumerate() {
objects.push(format!("<< /Type /Page /Parent 2 0 R /Resources << >> /Contents {} 0 R >>", 4 + i * 2));
let content = format!("{color} rg 0 0 200 300 re f");
objects.push(format!("<< /Length {} >>\nstream\n{content}\nendstream", content.len()));
}
let mut bytes = b"%PDF-1.7\n".to_vec();
let mut offsets = Vec::new();
for (i, object) in objects.iter().enumerate() {
offsets.push(bytes.len());
bytes.extend_from_slice(format!("{} 0 obj\n{object}\nendobj\n", i + 1).as_bytes());
}
let xref = bytes.len();
bytes.extend_from_slice(format!("xref\n0 {}\n0000000000 65535 f \n", objects.len() + 1).as_bytes());
for offset in offsets {
bytes.extend_from_slice(format!("{offset:010} 00000 n \n").as_bytes());
}
bytes.extend_from_slice(format!("trailer << /Size {} /Root 1 0 R >>\nstartxref\n{xref}\n%%EOF\n", objects.len() + 1).as_bytes());
let mut h = Harness::builder().with_size(egui::vec2(1400.0, 900.0)).build_eframe(move |_| {
let mut app = PdfCraftApp::new();
app.set_option("language", "en").unwrap();
app.open_bytes("labelled.pdf", None, bytes).unwrap();
app
});
h.run_steps(4);
let id = h.state().views[0].id;
let labels: Vec<_> = h.state().session.get(id).unwrap().info.pages.iter().map(|p| p.label.as_str()).collect();
assert_eq!(labels, ["i", "ii", "iii", "1", "2"]);
for (current, expected) in [[255, 0, 0], [0, 255, 0]].into_iter().enumerate() {
h.state_mut().set_option("page", &(current + 1).to_string()).unwrap();
h.run_steps(3);
assert!(h.state_mut().execute("print.dialog"));
h.run_steps(3);
h.get_by_label("Current page").click();
h.run_steps(3);
assert_eq!(h.state().print_draft.current_page, current);
h.get_by_label("Sheet 1 of 1");
let out = std::env::temp_dir().join(format!("pdfcraft-print-current-{}-{current}.pdf", std::process::id()));
h.state_mut().save_override = Some(out.to_string_lossy().into_owned());
h.state_mut().print_draft.printer = None;
h.run_steps(1);
h.get_by_label("Save as PDF").click();
h.run_steps(3);
assert_eq!(h.state().dialog, None);
let saved = std::sync::Arc::new(std::fs::read(&out).unwrap());
std::fs::remove_file(out).unwrap();
let doc = pdfcraft_cos::Document::open(saved.clone()).unwrap();
assert_eq!(pdfcraft_model::pages(&doc).len(), 1);
let mut renderer = pdfcraft_render::PageRenderer::new(saved, Default::default());
let shot = renderer.render(pdfcraft_render::RenderRequest { page: 0, scale: 1.0, ..Default::default() });
assert!(shot.error.is_none(), "{:?}", shot.error);
let center = ((shot.height / 2 * shot.width + shot.width / 2) * 4) as usize;
assert_eq!(&shot.rgba[center..center + 3], &expected, "saved the wrong physical page for {current}");
}
}
#[test]
fn print_dialog_lays_out_sheets_and_saves_a_pdf() {
let mut h = harness();