Merge pull request #2819 from ehuss/test-improvements
Various test improvements
This commit is contained in:
commit
73a1652b64
3 changed files with 53 additions and 12 deletions
7
Cargo.lock
generated
7
Cargo.lock
generated
|
|
@ -748,6 +748,12 @@ version = "0.31.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f"
|
checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "glob"
|
||||||
|
version = "0.3.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0cc23270f6e1808e30a928bdc84dea0b9b4136a8bc82338574f23baf47bbd280"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "globset"
|
name = "globset"
|
||||||
version = "0.4.16"
|
version = "0.4.16"
|
||||||
|
|
@ -1292,6 +1298,7 @@ dependencies = [
|
||||||
"clap_complete",
|
"clap_complete",
|
||||||
"env_logger",
|
"env_logger",
|
||||||
"futures-util",
|
"futures-util",
|
||||||
|
"glob",
|
||||||
"ignore",
|
"ignore",
|
||||||
"log",
|
"log",
|
||||||
"mdbook-core",
|
"mdbook-core",
|
||||||
|
|
|
||||||
|
|
@ -35,6 +35,7 @@ elasticlunr-rs = "3.0.2"
|
||||||
env_logger = "0.11.8"
|
env_logger = "0.11.8"
|
||||||
font-awesome-as-a-crate = "0.3.0"
|
font-awesome-as-a-crate = "0.3.0"
|
||||||
futures-util = "0.3.31"
|
futures-util = "0.3.31"
|
||||||
|
glob = "0.3.3"
|
||||||
handlebars = "6.3.2"
|
handlebars = "6.3.2"
|
||||||
hex = "0.4.3"
|
hex = "0.4.3"
|
||||||
indexmap = "2.10.0"
|
indexmap = "2.10.0"
|
||||||
|
|
@ -118,6 +119,7 @@ tokio = { workspace = true, features = ["macros", "rt-multi-thread"], optional =
|
||||||
tower-http = { workspace = true, features = ["fs", "trace"], optional = true }
|
tower-http = { workspace = true, features = ["fs", "trace"], optional = true }
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
|
glob.workspace = true
|
||||||
regex.workspace = true
|
regex.workspace = true
|
||||||
select.workspace = true
|
select.workspace = true
|
||||||
semver.workspace = true
|
semver.workspace = true
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
//! Utility for building and running tests against mdbook.
|
//! Utility for building and running tests against mdbook.
|
||||||
|
|
||||||
|
use anyhow::Context;
|
||||||
use mdbook_driver::MDBook;
|
use mdbook_driver::MDBook;
|
||||||
use mdbook_driver::init::BookBuilder;
|
use mdbook_driver::init::BookBuilder;
|
||||||
use snapbox::IntoData;
|
use snapbox::IntoData;
|
||||||
|
|
@ -91,6 +92,7 @@ impl BookTest {
|
||||||
///
|
///
|
||||||
/// Normally the contents outside of the `<main>` tag aren't interesting,
|
/// Normally the contents outside of the `<main>` tag aren't interesting,
|
||||||
/// and they add a significant amount of noise.
|
/// and they add a significant amount of noise.
|
||||||
|
#[track_caller]
|
||||||
pub fn check_main_file(&mut self, path: &str, expected: impl IntoData) -> &mut Self {
|
pub fn check_main_file(&mut self, path: &str, expected: impl IntoData) -> &mut Self {
|
||||||
if !self.built {
|
if !self.built {
|
||||||
self.build();
|
self.build();
|
||||||
|
|
@ -107,6 +109,7 @@ impl BookTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Checks the summary contents of `toc.js` against the expected value.
|
/// Checks the summary contents of `toc.js` against the expected value.
|
||||||
|
#[track_caller]
|
||||||
pub fn check_toc_js(&mut self, expected: impl IntoData) -> &mut Self {
|
pub fn check_toc_js(&mut self, expected: impl IntoData) -> &mut Self {
|
||||||
if !self.built {
|
if !self.built {
|
||||||
self.build();
|
self.build();
|
||||||
|
|
@ -119,6 +122,7 @@ impl BookTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the summary contents from `toc.js`.
|
/// Returns the summary contents from `toc.js`.
|
||||||
|
#[track_caller]
|
||||||
pub fn toc_js_html(&self) -> String {
|
pub fn toc_js_html(&self) -> String {
|
||||||
let full_path = self.dir.join("book/toc.js");
|
let full_path = self.dir.join("book/toc.js");
|
||||||
let actual = read_to_string(&full_path);
|
let actual = read_to_string(&full_path);
|
||||||
|
|
@ -135,27 +139,31 @@ impl BookTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Checks that the contents of the given file matches the expected value.
|
/// Checks that the contents of the given file matches the expected value.
|
||||||
pub fn check_file(&mut self, path: &str, expected: impl IntoData) -> &mut Self {
|
///
|
||||||
|
/// The path can use glob-style wildcards, but it must match only a single file.
|
||||||
|
#[track_caller]
|
||||||
|
pub fn check_file(&mut self, path_pattern: &str, expected: impl IntoData) -> &mut Self {
|
||||||
if !self.built {
|
if !self.built {
|
||||||
self.build();
|
self.build();
|
||||||
}
|
}
|
||||||
let path = self.dir.join(path);
|
let path = glob_one(&self.dir, path_pattern);
|
||||||
let actual = read_to_string(&path);
|
let actual = read_to_string(&path);
|
||||||
self.assert.eq(actual, expected);
|
self.assert.eq(actual, expected);
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Checks that the given file contains the given string somewhere.
|
/// Checks that the given file contains the given [`snapbox::Assert`] pattern somewhere.
|
||||||
pub fn check_file_contains(&mut self, path: &str, expected: &str) -> &mut Self {
|
///
|
||||||
|
/// The path can use glob-style wildcards, but it must match only a single file.
|
||||||
|
#[track_caller]
|
||||||
|
pub fn check_file_contains(&mut self, path_pattern: &str, expected: &str) -> &mut Self {
|
||||||
if !self.built {
|
if !self.built {
|
||||||
self.build();
|
self.build();
|
||||||
}
|
}
|
||||||
let path = self.dir.join(path);
|
let path = glob_one(&self.dir, path_pattern);
|
||||||
let actual = read_to_string(&path);
|
let actual = read_to_string(&path);
|
||||||
assert!(
|
let expected = format!("...\n[..]{expected}[..]\n...\n");
|
||||||
actual.contains(expected),
|
self.assert.eq(actual, expected);
|
||||||
"Did not find {expected:?} in {path:?}\n\n{actual}",
|
|
||||||
);
|
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -164,11 +172,14 @@ impl BookTest {
|
||||||
/// Beware that using this is fragile, as it may be unable to catch
|
/// Beware that using this is fragile, as it may be unable to catch
|
||||||
/// regressions (it can't tell the difference between success, or the
|
/// regressions (it can't tell the difference between success, or the
|
||||||
/// string being looked for changed).
|
/// string being looked for changed).
|
||||||
pub fn check_file_doesnt_contain(&mut self, path: &str, string: &str) -> &mut Self {
|
///
|
||||||
|
/// The path can use glob-style wildcards, but it must match only a single file.
|
||||||
|
#[track_caller]
|
||||||
|
pub fn check_file_doesnt_contain(&mut self, path_pattern: &str, string: &str) -> &mut Self {
|
||||||
if !self.built {
|
if !self.built {
|
||||||
self.build();
|
self.build();
|
||||||
}
|
}
|
||||||
let path = self.dir.join(path);
|
let path = glob_one(&self.dir, path_pattern);
|
||||||
let actual = read_to_string(&path);
|
let actual = read_to_string(&path);
|
||||||
assert!(
|
assert!(
|
||||||
!actual.contains(string),
|
!actual.contains(string),
|
||||||
|
|
@ -178,6 +189,7 @@ impl BookTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Checks that the list of files at the given path matches the given value.
|
/// Checks that the list of files at the given path matches the given value.
|
||||||
|
#[track_caller]
|
||||||
pub fn check_file_list(&mut self, path: &str, expected: impl IntoData) -> &mut Self {
|
pub fn check_file_list(&mut self, path: &str, expected: impl IntoData) -> &mut Self {
|
||||||
let mut all_paths: Vec<_> = walkdir::WalkDir::new(&self.dir.join(path))
|
let mut all_paths: Vec<_> = walkdir::WalkDir::new(&self.dir.join(path))
|
||||||
.into_iter()
|
.into_iter()
|
||||||
|
|
@ -499,5 +511,25 @@ fn assert(root: &Path) -> snapbox::Assert {
|
||||||
#[track_caller]
|
#[track_caller]
|
||||||
pub fn read_to_string<P: AsRef<Path>>(path: P) -> String {
|
pub fn read_to_string<P: AsRef<Path>>(path: P) -> String {
|
||||||
let path = path.as_ref();
|
let path = path.as_ref();
|
||||||
std::fs::read_to_string(path).unwrap_or_else(|e| panic!("could not read file {path:?}: {e:?}"))
|
std::fs::read_to_string(path)
|
||||||
|
.with_context(|| format!("could not read file {path:?}"))
|
||||||
|
.unwrap()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns the first path from the given glob pattern.
|
||||||
|
pub fn glob_one<P: AsRef<Path>>(path: P, pattern: &str) -> PathBuf {
|
||||||
|
let path = path.as_ref();
|
||||||
|
let mut matches = glob::glob(path.join(pattern).to_str().unwrap()).unwrap();
|
||||||
|
let Some(first) = matches.next() else {
|
||||||
|
panic!("expected at least one file at `{path:?}` with pattern `{pattern}`, found none");
|
||||||
|
};
|
||||||
|
let first = first.unwrap();
|
||||||
|
if let Some(next) = matches.next() {
|
||||||
|
panic!(
|
||||||
|
"expected only one file for pattern `{pattern}` in `{path:?}`, \
|
||||||
|
found `{first:?}` and `{:?}`",
|
||||||
|
next.unwrap()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
first
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue