Set Rules Episode V: The Tests Strike Back
@ -280,11 +280,11 @@ impl NodePacker {
|
|||||||
|
|
||||||
/// Advance to the next paragraph.
|
/// Advance to the next paragraph.
|
||||||
fn parbreak(&mut self, break_styles: Option<Styles>) {
|
fn parbreak(&mut self, break_styles: Option<Styles>) {
|
||||||
|
let styles = break_styles.unwrap_or_else(|| self.par_styles.clone());
|
||||||
self.finish_par();
|
self.finish_par();
|
||||||
|
|
||||||
// Insert paragraph spacing.
|
// Insert paragraph spacing.
|
||||||
self.flow_last
|
self.flow_last.soft(FlowChild::Parbreak(styles));
|
||||||
.soft(FlowChild::Parbreak(break_styles.unwrap_or_default()));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn finish_par(&mut self) {
|
fn finish_par(&mut self) {
|
||||||
|
@ -15,9 +15,19 @@ Running the integration tests (the tests in this directory).
|
|||||||
cargo test --test typeset
|
cargo test --test typeset
|
||||||
```
|
```
|
||||||
|
|
||||||
Running all tests whose names contain the word `filter`.
|
Running all tests whose paths contain the string `page` or `stack`.
|
||||||
```bash
|
```bash
|
||||||
cargo test --test typeset filter
|
cargo test --test typeset page stack
|
||||||
|
```
|
||||||
|
|
||||||
|
Running a test with the exact filename `page.typ`.
|
||||||
|
```bash
|
||||||
|
cargo test --test typeset -- --exact page.typ
|
||||||
|
```
|
||||||
|
|
||||||
|
Debug-printing the layout trees for all executed tests.
|
||||||
|
```bash
|
||||||
|
cargo test --test typeset -- --debug empty.typ
|
||||||
```
|
```
|
||||||
|
|
||||||
To make the integration tests go faster they don't generate PDFs by default.
|
To make the integration tests go faster they don't generate PDFs by default.
|
||||||
@ -39,3 +49,24 @@ oxipng -o max path/to/image.png
|
|||||||
# All images
|
# All images
|
||||||
oxipng -r -o max tests/ref
|
oxipng -r -o max tests/ref
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Shorthand for running tests
|
||||||
|
If you want to have a quicker way to run the tests, consider adding a shortcut
|
||||||
|
to your shell profile so that you can simply write something like:
|
||||||
|
```bash
|
||||||
|
tests --debug empty.typ
|
||||||
|
```
|
||||||
|
|
||||||
|
### PowerShell
|
||||||
|
Open your PowerShell profile by executing `notepad $profile`.
|
||||||
|
```ps
|
||||||
|
function tests {
|
||||||
|
cargo test --test typeset -- $args
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Bash
|
||||||
|
Open your Bash configuration by executing `nano ~/.bashrc`.
|
||||||
|
```bash
|
||||||
|
alias tests="cargo test --test typeset --"
|
||||||
|
```
|
||||||
|
Before Width: | Height: | Size: 18 KiB After Width: | Height: | Size: 18 KiB |
Before Width: | Height: | Size: 9.4 KiB After Width: | Height: | Size: 9.2 KiB |
Before Width: | Height: | Size: 3.1 KiB After Width: | Height: | Size: 3.7 KiB |
Before Width: | Height: | Size: 53 KiB After Width: | Height: | Size: 53 KiB |
Before Width: | Height: | Size: 6.3 KiB After Width: | Height: | Size: 6.3 KiB |
Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 22 KiB |
Before Width: | Height: | Size: 5.6 KiB After Width: | Height: | Size: 7.2 KiB |
@ -26,7 +26,7 @@
|
|||||||
{not ()}
|
{not ()}
|
||||||
|
|
||||||
---
|
---
|
||||||
// Error: 2-18 cannot apply '<=' to linear and relative
|
// Error: 2-18 cannot apply '<=' to relative length and relative
|
||||||
{30% + 1pt <= 40%}
|
{30% + 1pt <= 40%}
|
||||||
|
|
||||||
---
|
---
|
||||||
|
@ -64,7 +64,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Linears cannot be divided by themselves.
|
// Linears cannot be divided by themselves.
|
||||||
if type(v) != "linear" {
|
if type(v) != "relative length" {
|
||||||
test(v / v, 1.0)
|
test(v / v, 1.0)
|
||||||
test(v / v == 1, true)
|
test(v / v == 1, true)
|
||||||
}
|
}
|
||||||
@ -130,12 +130,14 @@
|
|||||||
#test(test == test, true)
|
#test(test == test, true)
|
||||||
#test((() => {}) == (() => {}), false)
|
#test((() => {}) == (() => {}), false)
|
||||||
|
|
||||||
// Templates also compare by identity.
|
// Templates compare by shallow equality.
|
||||||
#let t = [a]
|
#let t = [a]
|
||||||
#test(t == t, true)
|
#test(t == t, true)
|
||||||
#test([] == [], false)
|
#test([] == [], true)
|
||||||
|
#test([a] == [a], true)
|
||||||
#test([] == [a], false)
|
#test([] == [a], false)
|
||||||
#test([a] == [a], false)
|
#test([[a]] == [a], false)
|
||||||
|
#test(box[] == box[], false)
|
||||||
|
|
||||||
---
|
---
|
||||||
// Test comparison operators.
|
// Test comparison operators.
|
||||||
|
@ -8,7 +8,8 @@ Ola Nordmann, John Doe
|
|||||||
|
|
||||||
#v(6mm)
|
#v(6mm)
|
||||||
#align(center)[
|
#align(center)[
|
||||||
==== 3. Übungsblatt Computerorientierte Mathematik II #v(4mm)
|
==== 3. Übungsblatt Computerorientierte Mathematik II
|
||||||
|
#v(4mm)
|
||||||
*Abgabe: 03.05.2019* (bis 10:10 Uhr in MA 001) #v(4mm)
|
*Abgabe: 03.05.2019* (bis 10:10 Uhr in MA 001) #v(4mm)
|
||||||
*Alle Antworten sind zu beweisen.*
|
*Alle Antworten sind zu beweisen.*
|
||||||
]
|
]
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
// Test placing a background image on a page.
|
// Test placing a background image on a page.
|
||||||
|
|
||||||
---
|
---
|
||||||
#page(paper: "a10", flip: true)
|
#page(paper: "a10", flipped: true)
|
||||||
#font(fill: white)
|
#font(fill: white)
|
||||||
#place(
|
#place(
|
||||||
dx: -10pt,
|
dx: -10pt,
|
||||||
|
@ -24,7 +24,7 @@
|
|||||||
[#page(margins: 0pt, left: 20pt) Overriden]
|
[#page(margins: 0pt, left: 20pt) Overriden]
|
||||||
|
|
||||||
// Flipped predefined paper.
|
// Flipped predefined paper.
|
||||||
[#page(paper: "a11", flip: true) Flipped A11]
|
[#page(paper: "a11", flipped: true) Flipped A11]
|
||||||
|
|
||||||
---
|
---
|
||||||
#page(width: 80pt, height: 40pt, fill: eastern)
|
#page(width: 80pt, height: 40pt, fill: eastern)
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
First of two
|
First of two
|
||||||
#pagebreak()
|
#pagebreak()
|
||||||
#page(height: 40pt)
|
#page(height: 40pt)
|
||||||
|
Second of two
|
||||||
|
|
||||||
---
|
---
|
||||||
// Make sure that you can't do page related stuff in a container.
|
// Make sure that you can't do page related stuff in a container.
|
||||||
@ -24,11 +25,11 @@ D
|
|||||||
|
|
||||||
#page(width: 80pt, height: 30pt)
|
#page(width: 80pt, height: 30pt)
|
||||||
|
|
||||||
[#page() First]
|
Fi[#page(width: 80pt)rst]
|
||||||
[#page() Second]
|
[#page(width: 70pt) Second]
|
||||||
#pagebreak()
|
#pagebreak()
|
||||||
#pagebreak()
|
#pagebreak()
|
||||||
Fourth
|
Fourth
|
||||||
[#page(height: 25pt)]
|
#page(height: 20pt)[]
|
||||||
Sixth
|
Sixth
|
||||||
[#page() Seventh]
|
[#page() Seventh]
|
||||||
|
@ -20,3 +20,10 @@ You could also make the #link("https://html5zombo.com/")[link look way more typi
|
|||||||
#page(height: 60pt)
|
#page(height: 60pt)
|
||||||
#let link = link("https://typst.app/")[LINK]
|
#let link = link("https://typst.app/")[LINK]
|
||||||
My cool #move(x: 0.7cm, y: 0.7cm, rotate(10deg, scale(200%, link)))
|
My cool #move(x: 0.7cm, y: 0.7cm, rotate(10deg, scale(200%, link)))
|
||||||
|
|
||||||
|
---
|
||||||
|
// Link containing a block.
|
||||||
|
#link("https://example.com/", block[
|
||||||
|
My cool rhino
|
||||||
|
#move(x: 10pt, image("../../res/rhino.png", width: 1cm))
|
||||||
|
])
|
||||||
|
@ -5,6 +5,23 @@
|
|||||||
#par(align: right)
|
#par(align: right)
|
||||||
To the right! Where the sunlight peeks behind the mountain.
|
To the right! Where the sunlight peeks behind the mountain.
|
||||||
|
|
||||||
|
---
|
||||||
|
// Test that explicit paragraph break respects active styles.
|
||||||
|
#par(spacing: 7pt)
|
||||||
|
[#par(spacing: 100pt) First]
|
||||||
|
|
||||||
|
[#par(spacing: 100pt) Second]
|
||||||
|
#par(spacing: 20pt)
|
||||||
|
|
||||||
|
Third
|
||||||
|
|
||||||
|
---
|
||||||
|
// Test that paragraph break due to incompatibility respects
|
||||||
|
// spacing defined by the two adjacent paragraphs.
|
||||||
|
#let a = [#par(spacing: 40pt) Hello]
|
||||||
|
#let b = [#par(spacing: 60pt) World]
|
||||||
|
{a}{b}
|
||||||
|
|
||||||
---
|
---
|
||||||
// Test weird metrics.
|
// Test weird metrics.
|
||||||
#par(spacing: 100%, leading: 0pt)
|
#par(spacing: 100%, leading: 0pt)
|
||||||
|
@ -49,7 +49,7 @@ fn main() {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if args.matches(&src_path.to_string_lossy()) {
|
if args.matches(&src_path) {
|
||||||
filtered.push(src_path);
|
filtered.push(src_path);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -106,6 +106,7 @@ fn main() {
|
|||||||
&png_path,
|
&png_path,
|
||||||
&ref_path,
|
&ref_path,
|
||||||
pdf_path.as_deref(),
|
pdf_path.as_deref(),
|
||||||
|
args.debug,
|
||||||
) as usize;
|
) as usize;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -120,33 +121,43 @@ fn main() {
|
|||||||
|
|
||||||
struct Args {
|
struct Args {
|
||||||
filter: Vec<String>,
|
filter: Vec<String>,
|
||||||
|
exact: bool,
|
||||||
|
debug: bool,
|
||||||
pdf: bool,
|
pdf: bool,
|
||||||
perfect: bool,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Args {
|
impl Args {
|
||||||
fn new(args: impl Iterator<Item = String>) -> Self {
|
fn new(args: impl Iterator<Item = String>) -> Self {
|
||||||
let mut filter = Vec::new();
|
let mut filter = Vec::new();
|
||||||
let mut perfect = false;
|
let mut exact = false;
|
||||||
|
let mut debug = false;
|
||||||
let mut pdf = false;
|
let mut pdf = false;
|
||||||
|
|
||||||
for arg in args {
|
for arg in args {
|
||||||
match arg.as_str() {
|
match arg.as_str() {
|
||||||
|
// Ignore this, its for cargo.
|
||||||
"--nocapture" => {}
|
"--nocapture" => {}
|
||||||
|
// Match only the exact filename.
|
||||||
|
"--exact" => exact = true,
|
||||||
|
// Generate PDFs.
|
||||||
"--pdf" => pdf = true,
|
"--pdf" => pdf = true,
|
||||||
"=" => perfect = true,
|
// Debug print the layout trees.
|
||||||
|
"--debug" | "-d" => debug = true,
|
||||||
|
// Everything else is a file filter.
|
||||||
_ => filter.push(arg),
|
_ => filter.push(arg),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Self { filter, pdf, perfect }
|
Self { filter, pdf, debug, exact }
|
||||||
}
|
}
|
||||||
|
|
||||||
fn matches(&self, name: &str) -> bool {
|
fn matches(&self, path: &Path) -> bool {
|
||||||
if self.perfect {
|
if self.exact {
|
||||||
self.filter.iter().any(|p| name == p)
|
let name = path.file_name().unwrap().to_string_lossy();
|
||||||
|
self.filter.iter().any(|v| v == &name)
|
||||||
} else {
|
} else {
|
||||||
self.filter.is_empty() || self.filter.iter().any(|p| name.contains(p))
|
let path = path.to_string_lossy();
|
||||||
|
self.filter.is_empty() || self.filter.iter().any(|v| path.contains(v))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -157,6 +168,7 @@ fn test(
|
|||||||
png_path: &Path,
|
png_path: &Path,
|
||||||
ref_path: &Path,
|
ref_path: &Path,
|
||||||
pdf_path: Option<&Path>,
|
pdf_path: Option<&Path>,
|
||||||
|
debug: bool,
|
||||||
) -> bool {
|
) -> bool {
|
||||||
let name = src_path.strip_prefix(TYP_DIR).unwrap_or(src_path);
|
let name = src_path.strip_prefix(TYP_DIR).unwrap_or(src_path);
|
||||||
println!("Testing {}", name.display());
|
println!("Testing {}", name.display());
|
||||||
@ -185,7 +197,7 @@ fn test(
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
let (part_ok, compare_here, part_frames) =
|
let (part_ok, compare_here, part_frames) =
|
||||||
test_part(ctx, src_path, part.into(), i, compare_ref, line);
|
test_part(ctx, src_path, part.into(), i, compare_ref, line, debug);
|
||||||
ok &= part_ok;
|
ok &= part_ok;
|
||||||
compare_ever |= compare_here;
|
compare_ever |= compare_here;
|
||||||
frames.extend(part_frames);
|
frames.extend(part_frames);
|
||||||
@ -217,7 +229,10 @@ fn test(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if ok {
|
if ok {
|
||||||
println!("\x1b[1ATesting {} ✔", name.display());
|
if !debug {
|
||||||
|
print!("\x1b[1A");
|
||||||
|
}
|
||||||
|
println!("Testing {} ✔", name.display());
|
||||||
}
|
}
|
||||||
|
|
||||||
ok
|
ok
|
||||||
@ -230,6 +245,7 @@ fn test_part(
|
|||||||
i: usize,
|
i: usize,
|
||||||
compare_ref: bool,
|
compare_ref: bool,
|
||||||
line: usize,
|
line: usize,
|
||||||
|
debug: bool,
|
||||||
) -> (bool, bool, Vec<Rc<Frame>>) {
|
) -> (bool, bool, Vec<Rc<Frame>>) {
|
||||||
let id = ctx.sources.provide(src_path, src);
|
let id = ctx.sources.provide(src_path, src);
|
||||||
let source = ctx.sources.get(id);
|
let source = ctx.sources.get(id);
|
||||||
@ -240,7 +256,10 @@ fn test_part(
|
|||||||
let mut ok = true;
|
let mut ok = true;
|
||||||
let (frames, mut errors) = match ctx.execute(id) {
|
let (frames, mut errors) = match ctx.execute(id) {
|
||||||
Ok(document) => {
|
Ok(document) => {
|
||||||
// dbg!(&document);
|
if debug {
|
||||||
|
println!("{:#?}", document);
|
||||||
|
}
|
||||||
|
|
||||||
let mut frames = layout(ctx, &document);
|
let mut frames = layout(ctx, &document);
|
||||||
|
|
||||||
#[cfg(feature = "layout-cache")]
|
#[cfg(feature = "layout-cache")]
|
||||||
|