summaryrefslogtreecommitdiff
path: root/crates
diff options
context:
space:
mode:
authorLaurenz <laurmaedje@gmail.com>2024-05-30 14:06:36 +0200
committerGitHub <noreply@github.com>2024-05-30 12:06:36 +0000
commitfa7fbb82749f6e8a150fb81c1cdd0efeb80aba14 (patch)
treecaa2edf73a8dcf86fc3dd3eed59ce576bd60134e /crates
parent023b8068f70d6f94b432a918ecf7f09d5118ce46 (diff)
Tests for jump from click/cursor (#4297)
Diffstat (limited to 'crates')
-rw-r--r--crates/typst-ide/Cargo.toml2
-rw-r--r--crates/typst-ide/src/jump.rs76
-rw-r--r--crates/typst-ide/src/lib.rs29
3 files changed, 98 insertions, 9 deletions
diff --git a/crates/typst-ide/Cargo.toml b/crates/typst-ide/Cargo.toml
index 01f7a106..4e87f99b 100644
--- a/crates/typst-ide/Cargo.toml
+++ b/crates/typst-ide/Cargo.toml
@@ -22,7 +22,7 @@ serde = { workspace = true }
unscanny = { workspace = true }
[dev-dependencies]
-typst-assets = { workspace = true }
+typst-assets = { workspace = true, features = ["fonts"] }
typst-dev-assets = { workspace = true }
once_cell = { workspace = true }
diff --git a/crates/typst-ide/src/jump.rs b/crates/typst-ide/src/jump.rs
index 45186d5b..3427a0c5 100644
--- a/crates/typst-ide/src/jump.rs
+++ b/crates/typst-ide/src/jump.rs
@@ -126,11 +126,8 @@ pub fn jump_from_cursor(
let span = node.span();
for (i, page) in document.pages.iter().enumerate() {
- if let Some(pos) = find_in_frame(&page.frame, span) {
- return Some(Position {
- page: NonZeroUsize::new(i + 1).unwrap(),
- point: pos,
- });
+ if let Some(point) = find_in_frame(&page.frame, span) {
+ return Some(Position { page: NonZeroUsize::new(i + 1).unwrap(), point });
}
}
@@ -168,3 +165,72 @@ fn is_in_rect(pos: Point, size: Size, click: Point) -> bool {
&& pos.y <= click.y
&& pos.y + size.y >= click.y
}
+
+#[cfg(test)]
+mod tests {
+ use std::num::NonZeroUsize;
+
+ use typst::eval::Tracer;
+ use typst::layout::{Abs, Point, Position};
+
+ use super::{jump_from_click, jump_from_cursor, Jump};
+ use crate::tests::TestWorld;
+
+ fn point(x: f64, y: f64) -> Point {
+ Point::new(Abs::pt(x), Abs::pt(y))
+ }
+
+ fn cursor(cursor: usize) -> Option<Jump> {
+ Some(Jump::Source(TestWorld::main_id(), cursor))
+ }
+
+ fn pos(page: usize, x: f64, y: f64) -> Option<Position> {
+ Some(Position {
+ page: NonZeroUsize::new(page).unwrap(),
+ point: point(x, y),
+ })
+ }
+
+ macro_rules! assert_approx_eq {
+ ($l:expr, $r:expr) => {
+ assert!(($l.to_raw() - $r.to_raw()).abs() < 0.1, "{:?} ≉ {:?}", $l, $r);
+ };
+ }
+
+ #[track_caller]
+ fn test_click(text: &str, click: Point, expected: Option<Jump>) {
+ let world = TestWorld::new(text);
+ let doc = typst::compile(&world, &mut Tracer::new()).unwrap();
+ assert_eq!(jump_from_click(&world, &doc, &doc.pages[0].frame, click), expected);
+ }
+
+ #[track_caller]
+ fn test_cursor(text: &str, cursor: usize, expected: Option<Position>) {
+ let world = TestWorld::new(text);
+ let doc = typst::compile(&world, &mut Tracer::new()).unwrap();
+ let pos = jump_from_cursor(&doc, &world.main, cursor);
+ assert_eq!(pos.is_some(), expected.is_some());
+ if let (Some(pos), Some(expected)) = (pos, expected) {
+ assert_eq!(pos.page, expected.page);
+ assert_approx_eq!(pos.point.x, expected.point.x);
+ assert_approx_eq!(pos.point.y, expected.point.y);
+ }
+ }
+
+ #[test]
+ fn test_jump_from_click() {
+ let s = "*Hello* #box[ABC] World";
+ test_click(s, point(0.0, 0.0), None);
+ test_click(s, point(70.0, 5.0), None);
+ test_click(s, point(45.0, 15.0), cursor(14));
+ test_click(s, point(48.0, 15.0), cursor(15));
+ test_click(s, point(72.0, 10.0), cursor(20));
+ }
+
+ #[test]
+ fn test_jump_from_cursor() {
+ let s = "*Hello* #box[ABC] World";
+ test_cursor(s, 12, None);
+ test_cursor(s, 14, pos(1, 37.55, 16.58));
+ }
+}
diff --git a/crates/typst-ide/src/lib.rs b/crates/typst-ide/src/lib.rs
index 117e75ab..1f8562fd 100644
--- a/crates/typst-ide/src/lib.rs
+++ b/crates/typst-ide/src/lib.rs
@@ -95,9 +95,10 @@ fn summarize_font_family<'a>(variants: impl Iterator<Item = &'a FontInfo>) -> Ec
mod tests {
use once_cell::sync::Lazy;
use typst::diag::{FileError, FileResult};
- use typst::foundations::{Bytes, Datetime};
+ use typst::foundations::{Bytes, Datetime, Smart};
+ use typst::layout::{Abs, Margin, PageElem};
use typst::syntax::{FileId, Source};
- use typst::text::{Font, FontBook};
+ use typst::text::{Font, FontBook, TextElem, TextSize};
use typst::utils::LazyHash;
use typst::{Library, World};
@@ -117,6 +118,12 @@ mod tests {
let main = Source::detached(text);
Self { main, base: &*BASE }
}
+
+ /// The ID of the main file in a `TestWorld`.
+ pub fn main_id() -> FileId {
+ static ID: Lazy<FileId> = Lazy::new(|| Source::detached("").id());
+ *ID
+ }
}
impl World for TestWorld {
@@ -168,10 +175,26 @@ mod tests {
.collect();
Self {
- library: LazyHash::new(Library::default()),
+ library: LazyHash::new(library()),
book: LazyHash::new(FontBook::from_fonts(&fonts)),
fonts,
}
}
}
+
+ /// The extended standard library for testing.
+ fn library() -> Library {
+ // Set page width to 120pt with 10pt margins, so that the inner page is
+ // exactly 100pt wide. Page height is unbounded and font size is 10pt so
+ // that it multiplies to nice round numbers.
+ let mut lib = Library::default();
+ lib.styles
+ .set(PageElem::set_width(Smart::Custom(Abs::pt(120.0).into())));
+ lib.styles.set(PageElem::set_height(Smart::Auto));
+ lib.styles.set(PageElem::set_margin(Margin::splat(Some(Smart::Custom(
+ Abs::pt(10.0).into(),
+ )))));
+ lib.styles.set(TextElem::set_size(TextSize(Abs::pt(10.0).into())));
+ lib
+ }
}