diff options
| author | Laurenz <laurmaedje@gmail.com> | 2024-04-13 10:39:45 +0200 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2024-04-13 08:39:45 +0000 |
| commit | 020294fca9a7065d4b9cf4e677f606ebaaa29b00 (patch) | |
| tree | c0027ad22046e2726c22298461327823d6b88d53 /crates/typst-ide | |
| parent | 72dd79210602ecc799726fc096b078afbb47f299 (diff) | |
Better test runner (#3922)
Diffstat (limited to 'crates/typst-ide')
| -rw-r--r-- | crates/typst-ide/Cargo.toml | 5 | ||||
| -rw-r--r-- | crates/typst-ide/src/complete.rs | 31 | ||||
| -rw-r--r-- | crates/typst-ide/src/lib.rs | 85 |
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, + } + } + } +} |
