mirror of
https://github.com/typst/typst
synced 2025-06-29 00:32:53 +08:00
Simplify tooltip tests
This commit is contained in:
parent
5d003fb1b2
commit
3d1cad2bec
@ -1390,9 +1390,10 @@ mod tests {
|
|||||||
use std::collections::BTreeSet;
|
use std::collections::BTreeSet;
|
||||||
|
|
||||||
use typst::model::Document;
|
use typst::model::Document;
|
||||||
|
use typst::syntax::Source;
|
||||||
|
|
||||||
use super::{autocomplete, Completion};
|
use super::{autocomplete, Completion};
|
||||||
use crate::tests::TestWorld;
|
use crate::tests::{SourceExt, TestWorld};
|
||||||
|
|
||||||
type Response = Option<(usize, Vec<Completion>)>;
|
type Response = Option<(usize, Vec<Completion>)>;
|
||||||
|
|
||||||
@ -1465,21 +1466,17 @@ mod tests {
|
|||||||
#[track_caller]
|
#[track_caller]
|
||||||
fn test_with_world(world: &TestWorld, cursor: isize) -> Response {
|
fn test_with_world(world: &TestWorld, cursor: isize) -> Response {
|
||||||
let doc = typst::compile(&world).output.ok();
|
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]
|
#[track_caller]
|
||||||
fn test_with_world_and_doc(
|
fn test_full(
|
||||||
world: &TestWorld,
|
world: &TestWorld,
|
||||||
|
source: &Source,
|
||||||
doc: Option<&Document>,
|
doc: Option<&Document>,
|
||||||
cursor: isize,
|
cursor: isize,
|
||||||
) -> Response {
|
) -> Response {
|
||||||
let cursor = if cursor < 0 {
|
autocomplete(&world, doc, source, source.cursor(cursor), true)
|
||||||
world.main.len_bytes().checked_add_signed(cursor).unwrap()
|
|
||||||
} else {
|
|
||||||
cursor as usize
|
|
||||||
};
|
|
||||||
autocomplete(&world, doc, &world.main, cursor, true)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@ -1523,7 +1520,7 @@ mod tests {
|
|||||||
let end = world.main.len_bytes();
|
let end = world.main.len_bytes();
|
||||||
world.main.edit(end..end, " #cite()");
|
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_include(["netwok", "glacier-melt", "supplement"])
|
||||||
.must_exclude(["bib"]);
|
.must_exclude(["bib"]);
|
||||||
}
|
}
|
||||||
|
@ -111,6 +111,7 @@ mod tests {
|
|||||||
pub struct TestWorld {
|
pub struct TestWorld {
|
||||||
pub main: Source,
|
pub main: Source,
|
||||||
assets: HashMap<FileId, Bytes>,
|
assets: HashMap<FileId, Bytes>,
|
||||||
|
sources: HashMap<FileId, Source>,
|
||||||
base: &'static TestBase,
|
base: &'static TestBase,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -124,11 +125,12 @@ mod tests {
|
|||||||
Self {
|
Self {
|
||||||
main,
|
main,
|
||||||
assets: HashMap::new(),
|
assets: HashMap::new(),
|
||||||
|
sources: HashMap::new(),
|
||||||
base: singleton!(TestBase, TestBase::default()),
|
base: singleton!(TestBase, TestBase::default()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Add an additional file to the test world.
|
/// Add an additional asset file to the test world.
|
||||||
#[track_caller]
|
#[track_caller]
|
||||||
pub fn with_asset_by_name(mut self, filename: &str) -> Self {
|
pub fn with_asset_by_name(mut self, filename: &str) -> Self {
|
||||||
let id = FileId::new(None, VirtualPath::new(filename));
|
let id = FileId::new(None, VirtualPath::new(filename));
|
||||||
@ -138,6 +140,14 @@ mod tests {
|
|||||||
self
|
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`.
|
/// The ID of the main file in a `TestWorld`.
|
||||||
pub fn main_id() -> FileId {
|
pub fn main_id() -> FileId {
|
||||||
*singleton!(FileId, FileId::new(None, VirtualPath::new("main.typ")))
|
*singleton!(FileId, FileId::new(None, VirtualPath::new("main.typ")))
|
||||||
@ -160,6 +170,8 @@ mod tests {
|
|||||||
fn source(&self, id: FileId) -> FileResult<Source> {
|
fn source(&self, id: FileId) -> FileResult<Source> {
|
||||||
if id == self.main.id() {
|
if id == self.main.id() {
|
||||||
Ok(self.main.clone())
|
Ok(self.main.clone())
|
||||||
|
} else if let Some(source) = self.sources.get(&id) {
|
||||||
|
Ok(source.clone())
|
||||||
} else {
|
} else {
|
||||||
Err(FileError::NotFound(id.vpath().as_rootless_path().into()))
|
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.
|
/// Shared foundation of all test worlds.
|
||||||
struct TestBase {
|
struct TestBase {
|
||||||
library: LazyHash<Library>,
|
library: LazyHash<Library>,
|
||||||
|
@ -134,7 +134,7 @@ fn closure_tooltip(leaf: &LinkedNode) -> Option<Tooltip> {
|
|||||||
names.sort();
|
names.sort();
|
||||||
|
|
||||||
let tooltip = repr::separated_list(&names, "and");
|
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.
|
/// Tooltip text for a hovered length.
|
||||||
@ -256,32 +256,65 @@ mod tests {
|
|||||||
use typst::syntax::Side;
|
use typst::syntax::Side;
|
||||||
|
|
||||||
use super::{tooltip, Tooltip};
|
use super::{tooltip, Tooltip};
|
||||||
use crate::tests::TestWorld;
|
use crate::tests::{SourceExt, TestWorld};
|
||||||
|
|
||||||
fn text(text: &str) -> Option<Tooltip> {
|
type Response = Option<Tooltip>;
|
||||||
Some(Tooltip::Text(text.into()))
|
|
||||||
|
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> {
|
impl ResponseExt for Response {
|
||||||
Some(Tooltip::Code(code.into()))
|
#[track_caller]
|
||||||
|
fn must_be_none(&self) -> &Self {
|
||||||
|
assert_eq!(*self, None);
|
||||||
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
#[track_caller]
|
#[track_caller]
|
||||||
fn test(text: &str, cursor: usize, side: Side, expected: Option<Tooltip>) {
|
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: isize, side: Side) -> Response {
|
||||||
let world = TestWorld::new(text);
|
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();
|
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]
|
#[test]
|
||||||
fn test_tooltip() {
|
fn test_tooltip() {
|
||||||
test("#let x = 1 + 2", 5, Side::After, code("3"));
|
test("#let x = 1 + 2", 14, Side::After).must_be_none();
|
||||||
test("#let x = 1 + 2", 6, Side::Before, code("3"));
|
test("#let x = 1 + 2", 5, Side::After).must_be_code("3");
|
||||||
test("#let f(x) = x + y", 11, Side::Before, text("This closure captures `y`."));
|
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]
|
#[test]
|
||||||
fn test_empty_contextual() {
|
fn test_tooltip_empty_contextual() {
|
||||||
test("#{context}", 10, Side::Before, code("context()"));
|
test("#{context}", 10, Side::Before).must_be_code("context()");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_tooltip_closure() {
|
||||||
|
test("#let f(x) = x + y", 11, Side::Before)
|
||||||
|
.must_be_text("This closure captures `y`");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user