summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLaurenz <laurmaedje@gmail.com>2024-11-09 12:18:24 +0100
committerLaurenz <laurmaedje@gmail.com>2024-11-13 10:21:40 +0100
commit3d1cad2bec2d7f3f8705465ec91a82af491cf597 (patch)
tree20d1183662957f27cb54091df5fedf7029c97cdc
parent5d003fb1b2114a11fbdcc5390d03222bd159092c (diff)
Simplify tooltip tests
-rw-r--r--crates/typst-ide/src/complete.rs17
-rw-r--r--crates/typst-ide/src/lib.rs30
-rw-r--r--crates/typst-ide/src/tooltip.rs59
3 files changed, 82 insertions, 24 deletions
diff --git a/crates/typst-ide/src/complete.rs b/crates/typst-ide/src/complete.rs
index a1b5f1d2..dc6c9abe 100644
--- a/crates/typst-ide/src/complete.rs
+++ b/crates/typst-ide/src/complete.rs
@@ -1390,9 +1390,10 @@ mod tests {
use std::collections::BTreeSet;
use typst::model::Document;
+ use typst::syntax::Source;
use super::{autocomplete, Completion};
- use crate::tests::TestWorld;
+ use crate::tests::{SourceExt, TestWorld};
type Response = Option<(usize, Vec<Completion>)>;
@@ -1465,21 +1466,17 @@ mod tests {
#[track_caller]
fn test_with_world(world: &TestWorld, cursor: isize) -> Response {
let doc = typst::compile(&world).output.ok();
- test_with_world_and_doc(world, doc.as_ref(), cursor)
+ test_full(world, &world.main, doc.as_ref(), cursor)
}
#[track_caller]
- fn test_with_world_and_doc(
+ fn test_full(
world: &TestWorld,
+ source: &Source,
doc: Option<&Document>,
cursor: isize,
) -> Response {
- let cursor = if cursor < 0 {
- world.main.len_bytes().checked_add_signed(cursor).unwrap()
- } else {
- cursor as usize
- };
- autocomplete(&world, doc, &world.main, cursor, true)
+ autocomplete(&world, doc, source, source.cursor(cursor), true)
}
#[test]
@@ -1523,7 +1520,7 @@ mod tests {
let end = world.main.len_bytes();
world.main.edit(end..end, " #cite()");
- test_with_world_and_doc(&world, doc.as_ref(), -1)
+ test_full(&world, &world.main, doc.as_ref(), -1)
.must_include(["netwok", "glacier-melt", "supplement"])
.must_exclude(["bib"]);
}
diff --git a/crates/typst-ide/src/lib.rs b/crates/typst-ide/src/lib.rs
index 90fc125e..4c1542fd 100644
--- a/crates/typst-ide/src/lib.rs
+++ b/crates/typst-ide/src/lib.rs
@@ -111,6 +111,7 @@ mod tests {
pub struct TestWorld {
pub main: Source,
assets: HashMap<FileId, Bytes>,
+ sources: HashMap<FileId, Source>,
base: &'static TestBase,
}
@@ -124,11 +125,12 @@ mod tests {
Self {
main,
assets: HashMap::new(),
+ sources: HashMap::new(),
base: singleton!(TestBase, TestBase::default()),
}
}
- /// Add an additional file to the test world.
+ /// Add an additional asset file to the test world.
#[track_caller]
pub fn with_asset_by_name(mut self, filename: &str) -> Self {
let id = FileId::new(None, VirtualPath::new(filename));
@@ -138,6 +140,14 @@ mod tests {
self
}
+ /// Add an additional source file to the test world.
+ pub fn with_source(mut self, path: &str, text: &str) -> Self {
+ let id = FileId::new(None, VirtualPath::new(path));
+ let source = Source::new(id, text.into());
+ self.sources.insert(id, source);
+ self
+ }
+
/// The ID of the main file in a `TestWorld`.
pub fn main_id() -> FileId {
*singleton!(FileId, FileId::new(None, VirtualPath::new("main.typ")))
@@ -160,6 +170,8 @@ mod tests {
fn source(&self, id: FileId) -> FileResult<Source> {
if id == self.main.id() {
Ok(self.main.clone())
+ } else if let Some(source) = self.sources.get(&id) {
+ Ok(source.clone())
} else {
Err(FileError::NotFound(id.vpath().as_rootless_path().into()))
}
@@ -181,6 +193,22 @@ mod tests {
}
}
+ /// Extra methods for [`Source`].
+ pub trait SourceExt {
+ /// Negative cursors index from the back.
+ fn cursor(&self, cursor: isize) -> usize;
+ }
+
+ impl SourceExt for Source {
+ fn cursor(&self, cursor: isize) -> usize {
+ if cursor < 0 {
+ self.len_bytes().checked_add_signed(cursor).unwrap()
+ } else {
+ cursor as usize
+ }
+ }
+ }
+
/// Shared foundation of all test worlds.
struct TestBase {
library: LazyHash<Library>,
diff --git a/crates/typst-ide/src/tooltip.rs b/crates/typst-ide/src/tooltip.rs
index df93d1dc..318ff0ce 100644
--- a/crates/typst-ide/src/tooltip.rs
+++ b/crates/typst-ide/src/tooltip.rs
@@ -134,7 +134,7 @@ fn closure_tooltip(leaf: &LinkedNode) -> Option<Tooltip> {
names.sort();
let tooltip = repr::separated_list(&names, "and");
- Some(Tooltip::Text(eco_format!("This closure captures {tooltip}.")))
+ Some(Tooltip::Text(eco_format!("This closure captures {tooltip}")))
}
/// Tooltip text for a hovered length.
@@ -256,32 +256,65 @@ mod tests {
use typst::syntax::Side;
use super::{tooltip, Tooltip};
- use crate::tests::TestWorld;
+ use crate::tests::{SourceExt, TestWorld};
- fn text(text: &str) -> Option<Tooltip> {
- Some(Tooltip::Text(text.into()))
+ type Response = Option<Tooltip>;
+
+ trait ResponseExt {
+ fn must_be_none(&self) -> &Self;
+ fn must_be_text(&self, text: &str) -> &Self;
+ fn must_be_code(&self, code: &str) -> &Self;
}
- fn code(code: &str) -> Option<Tooltip> {
- Some(Tooltip::Code(code.into()))
+ impl ResponseExt for Response {
+ #[track_caller]
+ fn must_be_none(&self) -> &Self {
+ assert_eq!(*self, None);
+ self
+ }
+
+ #[track_caller]
+ fn must_be_text(&self, text: &str) -> &Self {
+ assert_eq!(*self, Some(Tooltip::Text(text.into())));
+ self
+ }
+
+ #[track_caller]
+ fn must_be_code(&self, code: &str) -> &Self {
+ assert_eq!(*self, Some(Tooltip::Code(code.into())));
+ self
+ }
}
#[track_caller]
- fn test(text: &str, cursor: usize, side: Side, expected: Option<Tooltip>) {
+ fn test(text: &str, cursor: isize, side: Side) -> Response {
let world = TestWorld::new(text);
+ test_with_world(&world, cursor, side)
+ }
+
+ #[track_caller]
+ fn test_with_world(world: &TestWorld, cursor: isize, side: Side) -> Response {
+ let source = &world.main;
let doc = typst::compile(&world).output.ok();
- assert_eq!(tooltip(&world, doc.as_ref(), &world.main, cursor, side), expected);
+ tooltip(&world, doc.as_ref(), source, source.cursor(cursor), side)
}
#[test]
fn test_tooltip() {
- test("#let x = 1 + 2", 5, Side::After, code("3"));
- test("#let x = 1 + 2", 6, Side::Before, code("3"));
- test("#let f(x) = x + y", 11, Side::Before, text("This closure captures `y`."));
+ test("#let x = 1 + 2", 14, Side::After).must_be_none();
+ test("#let x = 1 + 2", 5, Side::After).must_be_code("3");
+ test("#let x = 1 + 2", 6, Side::Before).must_be_code("3");
+ test("#let x = 1 + 2", 6, Side::Before).must_be_code("3");
+ }
+
+ #[test]
+ fn test_tooltip_empty_contextual() {
+ test("#{context}", 10, Side::Before).must_be_code("context()");
}
#[test]
- fn test_empty_contextual() {
- test("#{context}", 10, Side::Before, code("context()"));
+ fn test_tooltip_closure() {
+ test("#let f(x) = x + y", 11, Side::Before)
+ .must_be_text("This closure captures `y`");
}
}