nigig-org/crates/apps/nigig-ocr/tests/parity.rs
nigig-bot bdf8fc9694
Some checks failed
cad / cad-truth-gates (push) Has been cancelled
cad / cad-core-checks (push) Has been cancelled
cad / cad-consumers (push) Has been cancelled
doc-engine / engine (push) Has been cancelled
doc-engine / coverage (push) Has been cancelled
doc-engine / consumer (push) Has been cancelled
email / gates (push) Has been cancelled
email / email-domain (push) Has been cancelled
email / nigig-email (push) Has been cancelled
email / supply-chain (push) Has been cancelled
nigig-build (CAD) / supply-chain (push) Has been cancelled
nigig-build (CAD) / cad-module (push) Has been cancelled
nigig-build (CAD) / full-crate-check (push) Has been cancelled
nigig-build (CAD) / cad-engine-coverage (push) Has been cancelled
nigig-build (CAD) / doc-workspace-coverage (push) Has been cancelled
nigig-build (CAD) / cad-widget-coverage (push) Has been cancelled
nigig-map / test (push) Has been cancelled
nigig-site / Owned paths and honest test contracts (push) Has been cancelled
nigig-site / Cargo check-all-targets (push) Has been cancelled
nigig-site / Cargo clippy-site-owned (push) Has been cancelled
nigig-site / Cargo contained-media-export-fixtures (push) Has been cancelled
nigig-site / Cargo containment-storage-crypto (push) Has been cancelled
nigig-site / Cargo core-clippy (push) Has been cancelled
nigig-site / Cargo core-contracts (push) Has been cancelled
nigig-site / Cargo integration-non-live (push) Has been cancelled
nigig-site / Cargo production-dependency-containment (push) Has been cancelled
nigig-site / Cargo site02-crypto (push) Has been cancelled
nigig-site / Cargo site02-repository (push) Has been cancelled
nigig-site / Cargo site02-store (push) Has been cancelled
nigig-site / Cargo unit (push) Has been cancelled
nigig-site / SITE-02 native provider/filesystem (macos-latest) (push) Has been cancelled
nigig-site / SITE-02 native provider/filesystem (ubuntu-latest) (push) Has been cancelled
nigig-site / SITE-02 native provider/filesystem (windows-latest) (push) Has been cancelled
nigig-site / SITE-02 desktop runtime and normal shutdown (push) Has been cancelled
nigig-site / SITE-02 migration, recovery, and fault corpus (push) Has been cancelled
nigig-site / Media limits (explicitly skipped until enabled) (push) Has been cancelled
nigig-site / Real server interoperability (explicitly skipped until enabled) (push) Has been cancelled
nigig-site / Security and supply-chain baseline (push) Has been cancelled
repo hygiene / hygiene (push) Has been cancelled
sms / gates (push) Has been cancelled
sms / robius-sms (push) Has been cancelled
sms / android (push) Has been cancelled
sms / nigig-sms (push) Has been cancelled
sms / supply-chain (push) Has been cancelled
spreadsheet / engine-coverage (push) Has been cancelled
spreadsheet / ui-controller-coverage (push) Has been cancelled
traffic / gates (push) Has been cancelled
traffic / nigig-traffic (push) Has been cancelled
traffic / supply-chain (push) Has been cancelled
nigig-site / Release capability gate (push) Has been cancelled
nigig-ocr OCR-T1: real Tesseract engine, honest UI state, correct ingest/export
- providers/tesseract: system tesseract (TSV → text + normalized word boxes),
  installed-language detection; default_engine() picks Vision/Tesseract/none
- image_prep: decode, validate, apply rotation before recognition
- jobs: background OcrJob with progress, cancel, per-item results
- ui_state: no fake success toasts; clipboard/export/share report real outcomes
- ingest: real decode validation, size caps, shared PDF pages (no duplication)
- export: atomic writes, paginated multi-page PDF, refuse non-WinAnsi text
- capture: fixed drag anchor; settings: atomic save + applied to new files
- drop unused deps; tests: 78 pass incl. 5 real-OCR on a fixture
- EXECUTION_PLAN: correct overstated status
2026-09-26 18:35:10 +00:00

130 lines
4.3 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.

//! Integration: engine-side contracts behind the F1–F28 labels/selectors.
//! These use the test StubEngine; real recognition is covered by
//! `tests/real_ocr.rs`. Nothing here exercises the Makepad widget.
use nigig_ocr::{
format_processing_time, progress_label, run_all_pages, run_current_page, write_pdf_all,
write_pdf_single, write_txt_all, write_txt_single, CaptureMode, CaptureRect, Clipboard,
FileList, InMemoryClipboard, OcrLanguage, RegionState, Settings, StubEngine, UiAction, UiState,
};
/// A real (decodable) PNG — signature-only bytes are now rejected.
fn png() -> Vec<u8> {
include_bytes!("fixtures/hello.png").to_vec()
}
fn pdf() -> Vec<u8> {
b"%PDF-1.4 test".to_vec()
}
#[test]
fn f1_drop_images_and_pdfs() {
let mut s = UiState::new();
assert!(s.apply(UiAction::DropBytes(png())).starts_with("Added"));
assert!(s
.apply(UiAction::DropPdfPages(pdf(), 2))
.contains("2 pages"));
assert_eq!(s.files.len(), 3);
}
#[test]
fn f2_f3_capture_single_and_multi() {
let single = RegionState::new(CaptureMode::Single, true);
let multi = RegionState::new(CaptureMode::Multi, true);
assert!(single.should_close_after_capture());
assert!(!multi.should_close_after_capture());
let r = CaptureRect::new(0.0, 0.0, 100.0, 50.0);
assert!(r.is_valid() && r.area() == 5000.0);
}
#[test]
fn f7_f8_do_and_batch_with_tolerance() {
let e = StubEngine::with_text("t");
let mut l = FileList::new();
l.add(png()).unwrap();
l.add(png()).unwrap();
let mut items: Vec<nigig_ocr::FileItem> =
(0..l.len()).map(|i| l.get(i).unwrap().clone()).collect();
let r = run_current_page(&e, &mut items, 0).unwrap();
assert_eq!(r.text, "t");
let rs = run_all_pages(&e, &mut items);
assert_eq!(rs.len(), 2);
assert!(rs.iter().all(|x| x.is_ok()));
}
#[test]
fn f9_f10_f11_options_round_trip_via_ui() {
let mut s = UiState::new();
s.apply(UiAction::DropBytes(png()));
s.apply(UiAction::Language(OcrLanguage::German));
s.apply(UiAction::FastToggle(true));
s.apply(UiAction::CorrectionToggle(false));
let f = s.files.get(0).unwrap();
assert_eq!(f.options.language, OcrLanguage::German);
assert_eq!(f.options.level, nigig_ocr::OcrLevel::Fast);
assert!(!f.options.language_correction);
assert_eq!(OcrLanguage::all_popup().len(), 8);
}
#[test]
fn f13_f14_rotate_and_overlay() {
let mut s = UiState::new();
s.apply(UiAction::DropBytes(png()));
s.apply(UiAction::RotateRight);
assert_eq!(s.files.get(0).unwrap().rotate_degree, 90);
let before = s.overlay_on;
s.apply(UiAction::OverlayToggle);
assert_ne!(s.overlay_on, before);
}
#[test]
fn f15_f16_labels_and_progress() {
assert_eq!(progress_label(1, 2), "Running OCR... 1/2");
assert!(format_processing_time(42).contains("42 ms"));
assert_eq!(
nigig_ocr::result::result_count_label(0),
"No results found."
);
}
#[test]
fn f17_delete_current_and_all() {
let mut s = UiState::new();
s.apply(UiAction::DropBytes(png()));
s.apply(UiAction::DropBytes(png()));
s.apply(UiAction::DeleteCurrent);
assert_eq!(s.files.len(), 1);
s.apply(UiAction::DeleteAll);
assert!(s.files.is_empty());
assert_eq!(s.last_message, "All Files Deleted");
}
#[test]
fn f18_f19_f20_f21_export_copy_share() {
let mut c = InMemoryClipboard::default();
c.copy_text("abc").unwrap();
assert_eq!(c.last_copied().as_deref(), Some("abc"));
let d = std::env::temp_dir().join(format!("ocr-parity-{}", std::process::id()));
let _ = std::fs::create_dir_all(&d);
write_txt_single("hi", &d.join("a.txt")).unwrap();
write_txt_all(&[("a", "hi")], &d.join("all.txt")).unwrap();
write_pdf_single("hi", &d.join("a.pdf")).unwrap();
write_pdf_all(&["hi", "yo"], &d.join("all.pdf")).unwrap();
let mut s = UiState::new();
assert_eq!(s.apply(UiAction::Share), "Share is not implemented yet");
let _ = std::fs::remove_dir_all(&d);
}
#[test]
fn f23_f24_settings_and_theme() {
let s = Settings {
theme: nigig_ocr::settings::Theme::Dark,
..Settings::default()
};
let d = std::env::temp_dir().join(format!("ocr-parity-set-{}", std::process::id()));
let _ = std::fs::create_dir_all(&d);
let f = d.join("p.ini");
s.save(&f).unwrap();
assert_eq!(Settings::load(&f), s);
let _ = std::fs::remove_dir_all(&d);
}