summaryrefslogtreecommitdiff
path: root/crates/typst-ide
diff options
context:
space:
mode:
authorLaurenz <laurmaedje@gmail.com>2024-04-13 10:39:45 +0200
committerGitHub <noreply@github.com>2024-04-13 08:39:45 +0000
commit020294fca9a7065d4b9cf4e677f606ebaaa29b00 (patch)
treec0027ad22046e2726c22298461327823d6b88d53 /crates/typst-ide
parent72dd79210602ecc799726fc096b078afbb47f299 (diff)
Better test runner (#3922)
Diffstat (limited to 'crates/typst-ide')
-rw-r--r--crates/typst-ide/Cargo.toml5
-rw-r--r--crates/typst-ide/src/complete.rs31
-rw-r--r--crates/typst-ide/src/lib.rs85
3 files changed, 121 insertions, 0 deletions
diff --git a/crates/typst-ide/Cargo.toml b/crates/typst-ide/Cargo.toml
index 45a83d55..01f7a106 100644
--- a/crates/typst-ide/Cargo.toml
+++ b/crates/typst-ide/Cargo.toml
@@ -21,5 +21,10 @@ log = { workspace = true }
serde = { workspace = true }
unscanny = { workspace = true }
+[dev-dependencies]
+typst-assets = { workspace = true }
+typst-dev-assets = { workspace = true }
+once_cell = { workspace = true }
+
[lints]
workspace = true
diff --git a/crates/typst-ide/src/complete.rs b/crates/typst-ide/src/complete.rs
index be28a431..c758dd1c 100644
--- a/crates/typst-ide/src/complete.rs
+++ b/crates/typst-ide/src/complete.rs
@@ -1403,3 +1403,34 @@ impl<'a> CompletionContext<'a> {
}
}
}
+
+#[cfg(test)]
+mod tests {
+ use typst::eval::Tracer;
+
+ use super::autocomplete;
+ use crate::tests::TestWorld;
+
+ #[track_caller]
+ fn test(text: &str, cursor: usize, contains: &[&str], excludes: &[&str]) {
+ let world = TestWorld::new(text);
+ let doc = typst::compile(&world, &mut Tracer::new()).ok();
+ let (_, completions) =
+ autocomplete(&world, doc.as_ref(), &world.main, cursor, true)
+ .unwrap_or_default();
+
+ let labels: Vec<_> = completions.iter().map(|c| c.label.as_str()).collect();
+ for item in contains {
+ assert!(labels.contains(item), "{item:?} was not contained in {labels:?}");
+ }
+ for item in excludes {
+ assert!(!labels.contains(item), "{item:?} was not excluded in {labels:?}");
+ }
+ }
+
+ #[test]
+ fn test_autocomplete() {
+ test("#i", 2, &["int", "if conditional"], &["foo"]);
+ test("#().", 4, &["insert", "remove", "len", "all"], &["foo"]);
+ }
+}
diff --git a/crates/typst-ide/src/lib.rs b/crates/typst-ide/src/lib.rs
index bbfd56d9..3967aaad 100644
--- a/crates/typst-ide/src/lib.rs
+++ b/crates/typst-ide/src/lib.rs
@@ -90,3 +90,88 @@ fn summarize_font_family<'a>(variants: impl Iterator<Item = &'a FontInfo>) -> Ec
detail
}
+
+#[cfg(test)]
+mod tests {
+ use comemo::Prehashed;
+ use once_cell::sync::Lazy;
+ use typst::diag::{FileError, FileResult};
+ use typst::foundations::{Bytes, Datetime};
+ use typst::syntax::{FileId, Source};
+ use typst::text::{Font, FontBook};
+ use typst::{Library, World};
+
+ /// A world for IDE testing.
+ pub struct TestWorld {
+ pub main: Source,
+ base: &'static TestBase,
+ }
+
+ impl TestWorld {
+ /// Create a new world for a single test.
+ ///
+ /// This is cheap because the shared base for all test runs is lazily
+ /// initialized just once.
+ pub fn new(text: &str) -> Self {
+ static BASE: Lazy<TestBase> = Lazy::new(TestBase::default);
+ let main = Source::detached(text);
+ Self { main, base: &*BASE }
+ }
+ }
+
+ impl World for TestWorld {
+ fn library(&self) -> &Prehashed<Library> {
+ &self.base.library
+ }
+
+ fn book(&self) -> &Prehashed<FontBook> {
+ &self.base.book
+ }
+
+ fn main(&self) -> Source {
+ self.main.clone()
+ }
+
+ fn source(&self, id: FileId) -> FileResult<Source> {
+ if id == self.main.id() {
+ Ok(self.main.clone())
+ } else {
+ Err(FileError::NotFound(id.vpath().as_rootless_path().into()))
+ }
+ }
+
+ fn file(&self, id: FileId) -> FileResult<Bytes> {
+ Err(FileError::NotFound(id.vpath().as_rootless_path().into()))
+ }
+
+ fn font(&self, index: usize) -> Option<Font> {
+ Some(self.base.fonts[index].clone())
+ }
+
+ fn today(&self, _: Option<i64>) -> Option<Datetime> {
+ None
+ }
+ }
+
+ /// Shared foundation of all test worlds.
+ struct TestBase {
+ library: Prehashed<Library>,
+ book: Prehashed<FontBook>,
+ fonts: Vec<Font>,
+ }
+
+ impl Default for TestBase {
+ fn default() -> Self {
+ let fonts: Vec<_> = typst_assets::fonts()
+ .chain(typst_dev_assets::fonts())
+ .flat_map(|data| Font::iter(Bytes::from_static(data)))
+ .collect();
+
+ Self {
+ library: Prehashed::new(Library::default()),
+ book: Prehashed::new(FontBook::from_fonts(&fonts)),
+ fonts,
+ }
+ }
+ }
+}