test: typlite use snapshot_testing (#1717)

* feat: use snapshot_test

* test: add snapshots
This commit is contained in:
Myriad-Dreamin 2025-04-30 20:31:02 +08:00 committed by GitHub
parent 647cda29a0
commit c66d2996dd
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
43 changed files with 279 additions and 204 deletions

1
Cargo.lock generated
View file

@ -4750,6 +4750,7 @@ dependencies = [
"tinymist-analysis",
"tinymist-project",
"tinymist-std",
"tinymist-tests",
"typst",
"typst-svg",
"typst-syntax",

View file

@ -35,6 +35,7 @@ typst-syntax.workspace = true
[dev-dependencies]
insta.workspace = true
regex.workspace = true
tinymist-tests.workspace = true
[features]
default = ["cli", "embed-fonts", "no-content-hint"]

View file

@ -0,0 +1,11 @@
These again are dictionaries with the keys
- `description` (optional): The description for the argument.
See @@show-module() for outputting the results of this function.
- name (string): The name for the module.
- label-prefix (auto, string): The label-prefix for internal function
references. If `auto`, the label-prefix name will be the module name.
- nested something
- nested something 2
-> string

View file

@ -0,0 +1,16 @@
---
source: crates/typlite/src/tests.rs
expression: "conv(world, true)"
input_file: crates/typlite/src/fixtures/docs/nest_list.typ
---
These again are dictionaries with the keys
- <!-- typlite:begin:list-item 0 -->`description` (optional): The description for the argument.<!-- typlite:end:list-item 0 -->
See @@show-module() for outputting the results of this function.
- <!-- typlite:begin:list-item 0 -->name (string): The name for the module.<!-- typlite:end:list-item 0 -->
- <!-- typlite:begin:list-item 0 -->label-prefix (auto, string): The label-prefix for internal function
references. If `auto`, the label-prefix name will be the module name.
- <!-- typlite:begin:list-item 1 -->nested something<!-- typlite:end:list-item 1 -->
- <!-- typlite:begin:list-item 1 -->nested something 2<!-- typlite:end:list-item 1 --><!-- typlite:end:list-item 0 -->
-> string

View file

@ -0,0 +1,23 @@
---
source: crates/typlite/src/tests.rs
expression: "conv(world, true)"
input_file: crates/typlite/src/fixtures/docs/tidy.typ
---
These again are dictionaries with the keys
- <!-- typlite:begin:list-item 0 -->`description` (optional): The description for the argument.<!-- typlite:end:list-item 0 -->
- <!-- typlite:begin:list-item 0 -->`types` (optional): A list of accepted argument types.<!-- typlite:end:list-item 0 -->
- <!-- typlite:begin:list-item 0 -->`default` (optional): Default value for this argument.<!-- typlite:end:list-item 0 -->
See @@show-module() for outputting the results of this function.
- <!-- typlite:begin:list-item 0 -->content (string): Content of `.typ` file to analyze for docstrings.<!-- typlite:end:list-item 0 -->
- <!-- typlite:begin:list-item 0 -->name (string): The name for the module.<!-- typlite:end:list-item 0 -->
- <!-- typlite:begin:list-item 0 -->label-prefix (auto, string): The label-prefix for internal function
references. If `auto`, the label-prefix name will be the module name.<!-- typlite:end:list-item 0 -->
- <!-- typlite:begin:list-item 0 -->require-all-parameters (boolean): Require that all parameters of a
functions are documented and fail if some are not.<!-- typlite:end:list-item 0 -->
- <!-- typlite:begin:list-item 0 -->scope (dictionary): A dictionary of definitions that are then available
in all function and parameter descriptions.<!-- typlite:end:list-item 0 -->
- <!-- typlite:begin:list-item 0 -->preamble (string): Code to prepend to all code snippets shown with `#example()`.
This can for instance be used to import something from the scope.<!-- typlite:end:list-item 0 -->
-> string

View file

@ -0,0 +1,18 @@
These again are dictionaries with the keys
- `description` (optional): The description for the argument.
- `types` (optional): A list of accepted argument types.
- `default` (optional): Default value for this argument.
See @@show-module() for outputting the results of this function.
- content (string): Content of `.typ` file to analyze for docstrings.
- name (string): The name for the module.
- label-prefix (auto, string): The label-prefix for internal function
references. If `auto`, the label-prefix name will be the module name.
- require-all-parameters (boolean): Require that all parameters of a
functions are documented and fail if some are not.
- scope (dictionary): A dictionary of definitions that are then available
in all function and parameter descriptions.
- preamble (string): Code to prepend to all code snippets shown with `#example()`.
This can for instance be used to import something from the scope.
-> string

View file

@ -0,0 +1,2 @@
= Hello, World!
This is a typst document.

View file

@ -0,0 +1,2 @@
+ A
+ B

View file

@ -0,0 +1,2 @@
2. A
+ B

View file

@ -0,0 +1 @@
#figure(image("./fig.png", alt: "Content"), caption: "Caption")

View file

@ -0,0 +1 @@
#figure(image("./fig.png"))

View file

@ -0,0 +1 @@
#figure(image("./fig.png", alt: "Content"))

View file

@ -0,0 +1 @@
#image("./fig.png")

View file

@ -0,0 +1 @@
#image("./fig.png", alt: "Content")

View file

@ -0,0 +1 @@
https://example.com

View file

@ -0,0 +1 @@
#link("https://example.com")[Content]

View file

@ -0,0 +1 @@
#link("https://example.com")[Reverse *the World*]

View file

@ -0,0 +1,2 @@
- Some *item*
- Another _item_

View file

@ -0,0 +1,3 @@
$
1/2 + 1/3 = 5/6
$

View file

@ -0,0 +1 @@
$ integral x dif x $

View file

@ -0,0 +1 @@
$integral x dif x$

View file

@ -0,0 +1,50 @@
#outline()
== Heading 1
=== Heading 2
#link("https://example.com")[
This is a link to example.com
]
Inline `code` has `back-ticks around` it.
```cs
using System.IO.Compression;
#pragma warning disable 414, 3021
namespace MyApplication
{
[Obsolete("...")]
class Program : IInterface
{
public static List<int> JustDoIt(int count)
{
Console.WriteLine($"Hello {Name}!");
return new List<int>(new int[] { 1, 2, 3 })
}
}
}
```
Math inline: $E = m c^2$ and block:
$
E = m c^2
$
- First item
- Second item
+ First sub-item
+ Second sub-item
- First sub-sub-item
/ First term: First definition
#table(
columns: (1em,) * 20,
..range(20).map(x => [#x]),
)

View file

@ -0,0 +1 @@
Some inlined raw `a`, ```c b```

View file

@ -0,0 +1,7 @@
---
source: crates/typlite/src/tests.rs
expression: "conv(world, false)"
input_file: crates/typlite/src/fixtures/integration/base.typ
---
# Hello, World!
This is a typst document.

View file

@ -0,0 +1,7 @@
---
source: crates/typlite/src/tests.rs
expression: "conv(world, false)"
input_file: crates/typlite/src/fixtures/integration/enum.typ
---
1. A
1. B

View file

@ -0,0 +1,7 @@
---
source: crates/typlite/src/tests.rs
expression: "conv(world, false)"
input_file: crates/typlite/src/fixtures/integration/enum2.typ
---
2. A
1. B

View file

@ -0,0 +1,6 @@
---
source: crates/typlite/src/tests.rs
expression: "conv(world, false)"
input_file: crates/typlite/src/fixtures/integration/figure_caption.typ
---
![Caption, Content](./fig.png)

View file

@ -0,0 +1,6 @@
---
source: crates/typlite/src/tests.rs
expression: "conv(world, false)"
input_file: crates/typlite/src/fixtures/integration/figure_image.typ
---
![](./fig.png)

View file

@ -0,0 +1,6 @@
---
source: crates/typlite/src/tests.rs
expression: "conv(world, false)"
input_file: crates/typlite/src/fixtures/integration/figure_image_alt.typ
---
![Content](./fig.png)

View file

@ -0,0 +1,6 @@
---
source: crates/typlite/src/tests.rs
expression: "conv(world, false)"
input_file: crates/typlite/src/fixtures/integration/image.typ
---
![](./fig.png)

View file

@ -0,0 +1,6 @@
---
source: crates/typlite/src/tests.rs
expression: "conv(world, false)"
input_file: crates/typlite/src/fixtures/integration/image_alt.typ
---
![Content](./fig.png)

View file

@ -0,0 +1,6 @@
---
source: crates/typlite/src/tests.rs
expression: "conv(world, false)"
input_file: crates/typlite/src/fixtures/integration/link.typ
---
[https://example.com](https://example.com)

View file

@ -0,0 +1,6 @@
---
source: crates/typlite/src/tests.rs
expression: "conv(world, false)"
input_file: crates/typlite/src/fixtures/integration/link2.typ
---
[Content](https://example.com)

View file

@ -0,0 +1,6 @@
---
source: crates/typlite/src/tests.rs
expression: "conv(world, false)"
input_file: crates/typlite/src/fixtures/integration/link3.typ
---
[Reverse **the World**](https://example.com)

View file

@ -0,0 +1,7 @@
---
source: crates/typlite/src/tests.rs
expression: "conv(world, false)"
input_file: crates/typlite/src/fixtures/integration/list.typ
---
- Some **item**
- Another _item_

View file

@ -0,0 +1,6 @@
---
source: crates/typlite/src/tests.rs
expression: "conv(world, false)"
input_file: crates/typlite/src/fixtures/integration/math_block.typ
---
<p align="center"><picture><source media="(prefers-color-scheme: dark)" srcset="data:image-hash/svg+xml;base64,redacted"><img alt="typst-block" src="data:image-hash/svg+xml;base64,redacted" /></picture></p>

View file

@ -0,0 +1,6 @@
---
source: crates/typlite/src/tests.rs
expression: "conv(world, false)"
input_file: crates/typlite/src/fixtures/integration/math_block2.typ
---
<p align="center"><picture><source media="(prefers-color-scheme: dark)" srcset="data:image-hash/svg+xml;base64,redacted"><img alt="typst-block" src="data:image-hash/svg+xml;base64,redacted" /></picture></p>

View file

@ -0,0 +1,6 @@
---
source: crates/typlite/src/tests.rs
expression: "conv(world, false)"
input_file: crates/typlite/src/fixtures/integration/math_inline.typ
---
<picture><source media="(prefers-color-scheme: dark)" srcset="data:image-hash/svg+xml;base64,redacted"><img style="vertical-align: -0.35em" alt="typst-block" src="data:image-hash/svg+xml;base64,redacted" /></picture>

View file

@ -0,0 +1,6 @@
---
source: crates/typlite/src/tests.rs
expression: "conv(world, false)"
input_file: crates/typlite/src/fixtures/integration/outline.typ
---
failed to convert to markdown: unknown variable: outline

View file

@ -0,0 +1,6 @@
---
source: crates/typlite/src/tests.rs
expression: "conv(world, false)"
input_file: crates/typlite/src/fixtures/integration/raw_inline.typ
---
Some inlined raw `a`, `b`

View file

@ -1,166 +1,45 @@
mod model;
mod rendering;
use std::sync::{LazyLock, OnceLock};
use std::sync::OnceLock;
use regex::Regex;
use tinymist_project::{
font::FontResolverImpl, CompileFontArgs, EntryState, ExportTarget, LspUniverseBuilder,
};
use typst_syntax::Source;
use super::*;
fn conv_(s: &str, for_docs: bool) -> EcoString {
static FONT_RESOLVER: LazyLock<Arc<FontResolverImpl>> = LazyLock::new(|| {
Arc::new(
LspUniverseBuilder::resolve_fonts(CompileFontArgs::default())
.expect("cannot resolve default fonts"),
)
pub fn snapshot_testing(name: &str, f: &impl Fn(LspWorld, PathBuf)) {
tinymist_tests::snapshot_testing!(name, |verse, path| {
f(verse.snapshot(), path);
});
}
let cwd = std::env::current_dir().unwrap();
let main = Source::detached(s);
let mut universe = LspUniverseBuilder::build(
EntryState::new_rooted_by_id(cwd.as_path().into(), main.id()),
ExportTarget::Paged,
Default::default(),
Default::default(),
Default::default(),
FONT_RESOLVER.clone(),
);
let main_id = universe.main_id().unwrap();
universe
.map_shadow_by_id(main_id, Bytes::from_string(main.text().to_owned()))
.unwrap();
let world = universe.snapshot();
#[test]
fn convert() {
snapshot_testing("integration", &|world, _path| {
insta::assert_snapshot!(conv(world, false));
});
}
#[test]
fn convert_docs() {
snapshot_testing("docs", &|world, _path| {
insta::assert_snapshot!(conv(world, true));
});
}
fn conv(world: LspWorld, for_docs: bool) -> EcoString {
let converter = Typlite::new(Arc::new(world)).with_feature(TypliteFeat {
annotate_elem: for_docs,
..Default::default()
});
let res = converter.convert().unwrap();
static REG: OnceLock<Regex> = OnceLock::new();
let reg = REG.get_or_init(|| Regex::new(r#"data:image/svg\+xml;base64,([^"]+)"#).unwrap());
let res = reg.replace_all(&res, |_captures: &regex::Captures| {
"data:image-hash/svg+xml;base64,redacted"
});
match converter.convert() {
Ok(conv) => {
static REG: OnceLock<Regex> = OnceLock::new();
let reg =
REG.get_or_init(|| Regex::new(r#"data:image/svg\+xml;base64,([^"]+)"#).unwrap());
let res = reg.replace_all(&conv, |_captures: &regex::Captures| {
"data:image-hash/svg+xml;base64,redacted"
});
res.into()
}
fn conv(s: &str) -> EcoString {
conv_(s, false)
}
fn conv_docs(s: &str) -> EcoString {
conv_(s, true)
}
#[test]
fn test_converted() {
insta::assert_snapshot!(conv(r###"
= Hello, World!
This is a typst document.
"###), @r"
# Hello, World!
This is a typst document.
");
insta::assert_snapshot!(conv(r###"
Some inlined raw `a`, ```c b```
"###), @"Some inlined raw `a`, `b`");
insta::assert_snapshot!(conv(r###"
- Some *item*
- Another _item_
"###), @r"
- Some **item**
- Another _item_
");
insta::assert_snapshot!(conv(r###"
+ A
+ B
"###), @r"
1. A
1. B
");
insta::assert_snapshot!(conv(r###"
2. A
+ B
"###), @r"
2. A
1. B
");
insta::assert_snapshot!(conv(r###"
$
1/2 + 1/3 = 5/6
$
"###), @r#"<p align="center"><picture><source media="(prefers-color-scheme: dark)" srcset="data:image-hash/svg+xml;base64,redacted"><img alt="typst-block" src="data:image-hash/svg+xml;base64,redacted" /></picture></p>"#);
}
#[test]
fn test_converted_docs() {
insta::assert_snapshot!(conv_docs(r###"
These again are dictionaries with the keys
- `description` (optional): The description for the argument.
- `types` (optional): A list of accepted argument types.
- `default` (optional): Default value for this argument.
See @@show-module() for outputting the results of this function.
- content (string): Content of `.typ` file to analyze for docstrings.
- name (string): The name for the module.
- label-prefix (auto, string): The label-prefix for internal function
references. If `auto`, the label-prefix name will be the module name.
- require-all-parameters (boolean): Require that all parameters of a
functions are documented and fail if some are not.
- scope (dictionary): A dictionary of definitions that are then available
in all function and parameter descriptions.
- preamble (string): Code to prepend to all code snippets shown with `#example()`.
This can for instance be used to import something from the scope.
-> string
"###), @r"
These again are dictionaries with the keys
- <!-- typlite:begin:list-item 0 -->`description` (optional): The description for the argument.<!-- typlite:end:list-item 0 -->
- <!-- typlite:begin:list-item 0 -->`types` (optional): A list of accepted argument types.<!-- typlite:end:list-item 0 -->
- <!-- typlite:begin:list-item 0 -->`default` (optional): Default value for this argument.<!-- typlite:end:list-item 0 -->
See @@show-module() for outputting the results of this function.
- <!-- typlite:begin:list-item 0 -->content (string): Content of `.typ` file to analyze for docstrings.<!-- typlite:end:list-item 0 -->
- <!-- typlite:begin:list-item 0 -->name (string): The name for the module.<!-- typlite:end:list-item 0 -->
- <!-- typlite:begin:list-item 0 -->label-prefix (auto, string): The label-prefix for internal function
references. If `auto`, the label-prefix name will be the module name.<!-- typlite:end:list-item 0 -->
- <!-- typlite:begin:list-item 0 -->require-all-parameters (boolean): Require that all parameters of a
functions are documented and fail if some are not.<!-- typlite:end:list-item 0 -->
- <!-- typlite:begin:list-item 0 -->scope (dictionary): A dictionary of definitions that are then available
in all function and parameter descriptions.<!-- typlite:end:list-item 0 -->
- <!-- typlite:begin:list-item 0 -->preamble (string): Code to prepend to all code snippets shown with `#example()`.
This can for instance be used to import something from the scope.<!-- typlite:end:list-item 0 -->
-> string
");
insta::assert_snapshot!(conv_docs(r###"
These again are dictionaries with the keys
- `description` (optional): The description for the argument.
See @@show-module() for outputting the results of this function.
- name (string): The name for the module.
- label-prefix (auto, string): The label-prefix for internal function
references. If `auto`, the label-prefix name will be the module name.
- nested something
- nested something 2
-> string
"###), @r"
These again are dictionaries with the keys
- <!-- typlite:begin:list-item 0 -->`description` (optional): The description for the argument.<!-- typlite:end:list-item 0 -->
See @@show-module() for outputting the results of this function.
- <!-- typlite:begin:list-item 0 -->name (string): The name for the module.<!-- typlite:end:list-item 0 -->
- <!-- typlite:begin:list-item 0 -->label-prefix (auto, string): The label-prefix for internal function
references. If `auto`, the label-prefix name will be the module name.
- <!-- typlite:begin:list-item 1 -->nested something<!-- typlite:end:list-item 1 -->
- <!-- typlite:begin:list-item 1 -->nested something 2<!-- typlite:end:list-item 1 --><!-- typlite:end:list-item 0 -->
-> string
");
res.into()
}
Err(err) => format!("failed to convert to markdown: {err}").into(),
}
}

View file

@ -1,41 +0,0 @@
use super::*;
#[test]
fn test_simple_link() {
insta::assert_snapshot!(conv(r###"
https://example.com
"###), @"[https://example.com](https://example.com)");
insta::assert_snapshot!(conv(r###"
#link("https://example.com")[Content]
"###), @"[Content](https://example.com)");
}
#[test]
fn test_nested_link() {
insta::assert_snapshot!(conv(r###"
#link("https://example.com")[Reverse *the World*]
"###), @"[Reverse **the World**](https://example.com)");
}
#[test]
fn test_simple_image() {
insta::assert_snapshot!(conv(r###"
#image("./fig.png")
"###), @"![](./fig.png)");
insta::assert_snapshot!(conv(r###"
#image("./fig.png", alt: "Content")
"###), @"![Content](./fig.png)");
}
#[test]
fn test_simple_figure() {
insta::assert_snapshot!(conv(r###"
#figure(image("./fig.png"))
"###), @"![](./fig.png)");
insta::assert_snapshot!(conv(r###"
#figure(image("./fig.png", alt: "Content"))
"###), @"![Content](./fig.png)");
insta::assert_snapshot!(conv(r###"
#figure(image("./fig.png", alt: "Content"), caption: "Caption")
"###), @"![Caption, Content](./fig.png)");
}

View file

@ -1,11 +0,0 @@
use crate::tests::*;
#[test]
fn test_math_equation() {
insta::assert_snapshot!(conv(r###"
$integral x dif x$
"###), @r#"<picture><source media="(prefers-color-scheme: dark)" srcset="data:image-hash/svg+xml;base64,redacted"><img style="vertical-align: -0.35em" alt="typst-block" src="data:image-hash/svg+xml;base64,redacted" /></picture>"#);
insta::assert_snapshot!(conv(r###"
$ integral x dif x $
"###), @r#"<p align="center"><picture><source media="(prefers-color-scheme: dark)" srcset="data:image-hash/svg+xml;base64,redacted"><img alt="typst-block" src="data:image-hash/svg+xml;base64,redacted" /></picture></p>"#);
}