#![allow(clippy::expect_used)]
use pdfrum::{Document, FormSession, Key, Modifiers, PageIndex, Point};
fn document() -> Document {
Document::open("tests/fixtures/annotiter.pdf").expect("the annotiter fixture must open")
}
fn tab(session: &mut FormSession<'_>, modifiers: Modifiers) -> bool {
session.key_down(Key::Tab, modifiers).consumed
}
fn focused(session: &FormSession<'_>) -> Option<u32> {
session.focused_annot().map(|annot| annot.index)
}
fn walk(page: u32, modifiers: Modifiers) -> Vec<u32> {
let doc = document();
let mut session = FormSession::new(&doc);
session.set_viewed_page(page);
let mut visited = Vec::new();
while tab(&mut session, modifiers) {
visited.push(focused(&session).expect("a consumed Tab lands somewhere"));
}
visited
}
#[test]
fn a_first_tab_lands_on_annot_one() {
let doc = document();
let mut session = FormSession::new(&doc);
assert!(session.focused_annot().is_none());
assert!(tab(&mut session, Modifiers::NONE));
assert_eq!(focused(&session), Some(1));
}
#[test]
fn a_first_shift_tab_lands_on_annot_zero() {
let doc = document();
let mut session = FormSession::new(&doc);
assert!(tab(&mut session, Modifiers::SHIFT));
assert_eq!(focused(&session), Some(0));
}
#[test]
fn four_tabs_visit_one_two_three_zero_and_the_fifth_is_refused() {
assert_eq!(walk(0, Modifiers::NONE), vec![1, 2, 3, 0]);
}
#[test]
fn four_shift_tabs_visit_zero_three_two_one_and_the_fifth_is_refused() {
assert_eq!(walk(0, Modifiers::SHIFT), vec![0, 3, 2, 1]);
}
#[test]
fn each_pages_declared_order_produces_its_own_walk() {
assert_eq!(walk(0, Modifiers::NONE), vec![1, 2, 3, 0], "/Tabs /R");
assert_eq!(walk(1, Modifiers::NONE), vec![1, 3, 2, 0], "/Tabs /C");
assert_eq!(walk(2, Modifiers::NONE), vec![0, 1, 2, 3], "/Tabs /S");
}
#[test]
fn tab_with_any_modifier_but_shift_is_refused() {
let doc = document();
for modifiers in [
Modifiers::CONTROL,
Modifiers::ALT,
Modifiers::META,
Modifiers::CONTROL.union(Modifiers::SHIFT),
Modifiers::ALT.union(Modifiers::SHIFT),
Modifiers::META.union(Modifiers::SHIFT),
] {
let mut session = FormSession::new(&doc);
assert!(
!tab(&mut session, modifiers),
"Tab with {modifiers:?} must be refused"
);
assert!(session.focused_annot().is_none(), "and must not move focus");
}
}
#[test]
fn focus_is_document_wide_not_per_page() {
let doc = document();
let mut session = FormSession::new(&doc);
assert_eq!(doc.page_count(), 3);
session.mouse_move(0, Point::new(210.0, 210.0), Modifiers::NONE);
session.mouse_down(0, Point::new(210.0, 210.0), Modifiers::NONE);
session.mouse_up(0, Point::new(210.0, 210.0), Modifiers::NONE);
let first = session
.focused_annot()
.expect("page 0's widget takes focus");
assert_eq!(first.page, PageIndex::new(0));
session.mouse_move(1, Point::new(411.0, 411.0), Modifiers::NONE);
session.mouse_down(1, Point::new(411.0, 411.0), Modifiers::NONE);
session.mouse_up(1, Point::new(411.0, 411.0), Modifiers::NONE);
let second = session.focused_annot().expect("page 1's widget takes it");
assert_eq!(
second.page,
PageIndex::new(1),
"focus moved to the other page"
);
assert_ne!(
first, second,
"one annotation holds the keyboard at a time, whichever page it is on"
);
}
#[test]
fn keys_with_no_focused_annotation_are_refused() {
let doc = document();
for key in [
Key::Newline,
Key::Return,
Key::Space,
Key::Delete,
Key::from_virtual(0x30), Key::from_virtual(0x39), Key::A,
Key::Z, Key::from_virtual(0x70), ] {
let mut session = FormSession::new(&doc);
let response = session.key_down(key, Modifiers::NONE);
assert!(!response.consumed, "{key:?} must not be handled");
assert!(
session.focused_annot().is_none(),
"{key:?} must not create a focus"
);
}
}
#[test]
fn opening_a_document_produces_no_updates() {
let doc = document();
let session = FormSession::new(&doc);
assert!(session.focused_annot().is_none());
assert!(session.focused_text().is_none());
assert!(!session.can_undo());
assert!(!session.can_redo());
}
#[test]
fn a_mouse_move_over_nothing_is_harmless() {
let doc = document();
let mut session = FormSession::new(&doc);
assert!(
!session
.mouse_move(0, Point::new(0.0, 0.0), Modifiers::NONE)
.consumed
);
assert!(
!session
.mouse_move(0, Point::new(-1000.0, -1000.0), Modifiers::NONE)
.consumed
);
assert!(
!session
.mouse_move(0, Point::new(1e9, 1e9), Modifiers::NONE)
.consumed
);
assert!(session.focused_annot().is_none());
}
#[test]
fn a_tab_from_nothing_enters_the_ring_on_the_viewed_page() {
let doc = document();
for page in 0..doc.page_count() {
let mut session = FormSession::new(&doc);
session.set_viewed_page(page);
assert_eq!(session.viewed_page(), PageIndex::from(page));
assert!(tab(&mut session, Modifiers::NONE));
let landed = session.focused_annot().expect("the Tab lands somewhere");
assert_eq!(
landed.page,
PageIndex::from(page),
"a Tab from nothing must enter the ring on the viewed page"
);
}
}
#[test]
fn the_viewed_page_defaults_to_the_first() {
let doc = document();
let session = FormSession::new(&doc);
assert_eq!(session.viewed_page(), PageIndex::FIRST);
}