diff options
Diffstat (limited to 'vendor/snapbox/src/lib.rs')
-rw-r--r-- | vendor/snapbox/src/lib.rs | 246 |
1 files changed, 246 insertions, 0 deletions
diff --git a/vendor/snapbox/src/lib.rs b/vendor/snapbox/src/lib.rs new file mode 100644 index 000000000..61419fd5e --- /dev/null +++ b/vendor/snapbox/src/lib.rs @@ -0,0 +1,246 @@ +//! # Snapshot testing toolbox +//! +//! > When you have to treat your tests like pets, instead of [cattle][trycmd] +//! +//! `snapbox` is a snapshot-testing toolbox that is ready to use for verifying output from +//! - Function return values +//! - CLI stdout/stderr +//! - Filesystem changes +//! +//! It is also flexible enough to build your own test harness like [trycmd](https://crates.io/crates/trycmd). +//! +//! ## Which tool is right +//! +//! - [cram](https://bitheap.org/cram/): End-to-end CLI snapshotting agnostic of any programming language +//! - [trycmd](https://crates.io/crates/trycmd): For running a lot of blunt tests (limited test predicates) +//! - Particular attention is given to allow the test data to be pulled into documentation, like +//! with [mdbook](https://rust-lang.github.io/mdBook/) +//! - `snapbox`: When you want something like `trycmd` in one off +//! cases or you need to customize `trycmd`s behavior. +//! - [assert_cmd](https://crates.io/crates/assert_cmd) + +//! [assert_fs](https://crates.io/crates/assert_fs): Test cases follow a certain pattern but +//! special attention is needed in how to verify the results. +//! - Hand-written test cases: for peculiar circumstances +//! +//! ## Getting Started +//! +//! Testing Functions: +//! - [`assert_eq`][crate::assert_eq] and [`assert_matches`] for reusing diffing / pattern matching for non-snapshot testing +//! - [`assert_eq_path`][crate::assert_eq_path] and [`assert_matches_path`] for one-off assertions with the snapshot stored in a file +//! - [`harness::Harness`] for discovering test inputs and asserting against snapshot files: +//! +//! Testing Commands: +//! - [`cmd::Command`]: Process spawning for testing of non-interactive commands +//! - [`cmd::OutputAssert`]: Assert the state of a [`Command`][cmd::Command]'s +//! [`Output`][std::process::Output]. +//! +//! Testing Filesystem Interactions: +//! - [`path::PathFixture`]: Working directory for tests +//! - [`Assert`]: Diff a directory against files present in a pattern directory +//! +//! You can also build your own version of these with the lower-level building blocks these are +//! made of. +//! +#![cfg_attr(feature = "document-features", doc = document_features::document_features!())] +//! +//! # Examples +//! +//! [`assert_matches`] +//! ```rust +//! snapbox::assert_matches("Hello [..] people!", "Hello many people!"); +//! ``` +//! +//! [`Assert`] +//! ```rust,no_run +//! let actual = "..."; +//! let expected_path = "tests/fixtures/help_output_is_clean.txt"; +//! snapbox::Assert::new() +//! .action_env("SNAPSHOTS") +//! .matches_path(expected_path, actual); +//! ``` +//! +//! [`harness::Harness`] +#![cfg_attr(not(feature = "harness"), doc = " ```rust,ignore")] +#![cfg_attr(feature = "harness", doc = " ```rust,no_run")] +//! snapbox::harness::Harness::new( +//! "tests/fixtures/invalid", +//! setup, +//! test, +//! ) +//! .select(["tests/cases/*.in"]) +//! .action_env("SNAPSHOTS") +//! .test(); +//! +//! fn setup(input_path: std::path::PathBuf) -> snapbox::harness::Case { +//! let name = input_path.file_name().unwrap().to_str().unwrap().to_owned(); +//! let expected = input_path.with_extension("out"); +//! snapbox::harness::Case { +//! name, +//! fixture: input_path, +//! expected, +//! } +//! } +//! +//! fn test(input_path: &std::path::Path) -> Result<usize, Box<dyn std::error::Error>> { +//! let raw = std::fs::read_to_string(input_path)?; +//! let num = raw.parse::<usize>()?; +//! +//! let actual = num + 10; +//! +//! Ok(actual) +//! } +//! ``` +//! +//! [trycmd]: https://docs.rs/trycmd + +#![cfg_attr(docsrs, feature(doc_auto_cfg))] + +mod action; +mod assert; +mod data; +mod error; +mod substitutions; + +pub mod cmd; +pub mod path; +pub mod report; +pub mod utils; + +#[cfg(feature = "harness")] +pub mod harness; + +pub use action::Action; +pub use action::DEFAULT_ACTION_ENV; +pub use assert::Assert; +pub use data::Data; +pub use data::DataFormat; +pub use data::{Normalize, NormalizeMatches, NormalizeNewlines, NormalizePaths}; +pub use error::Error; +pub use snapbox_macros::debug; +pub use substitutions::Substitutions; + +pub type Result<T, E = Error> = std::result::Result<T, E>; + +/// Check if a value is the same as an expected value +/// +/// When the content is text, newlines are normalized. +/// +/// ```rust +/// let output = "something"; +/// let expected = "something"; +/// snapbox::assert_matches(expected, output); +/// ``` +#[track_caller] +pub fn assert_eq(expected: impl Into<crate::Data>, actual: impl Into<crate::Data>) { + Assert::new().eq(expected, actual); +} + +/// Check if a value matches a pattern +/// +/// Pattern syntax: +/// - `...` is a line-wildcard when on a line by itself +/// - `[..]` is a character-wildcard when inside a line +/// - `[EXE]` matches `.exe` on Windows +/// +/// Normalization: +/// - Newlines +/// - `\` to `/` +/// +/// ```rust +/// let output = "something"; +/// let expected = "so[..]g"; +/// snapbox::assert_matches(expected, output); +/// ``` +#[track_caller] +pub fn assert_matches(pattern: impl Into<crate::Data>, actual: impl Into<crate::Data>) { + Assert::new().matches(pattern, actual); +} + +/// Check if a value matches the content of a file +/// +/// When the content is text, newlines are normalized. +/// +/// ```rust,no_run +/// let output = "something"; +/// let expected_path = "tests/snapshots/output.txt"; +/// snapbox::assert_eq_path(expected_path, output); +/// ``` +#[track_caller] +pub fn assert_eq_path(expected_path: impl AsRef<std::path::Path>, actual: impl Into<crate::Data>) { + Assert::new() + .action_env(DEFAULT_ACTION_ENV) + .eq_path(expected_path, actual); +} + +/// Check if a value matches the pattern in a file +/// +/// Pattern syntax: +/// - `...` is a line-wildcard when on a line by itself +/// - `[..]` is a character-wildcard when inside a line +/// - `[EXE]` matches `.exe` on Windows +/// +/// Normalization: +/// - Newlines +/// - `\` to `/` +/// +/// ```rust,no_run +/// let output = "something"; +/// let expected_path = "tests/snapshots/output.txt"; +/// snapbox::assert_matches_path(expected_path, output); +/// ``` +#[track_caller] +pub fn assert_matches_path( + pattern_path: impl AsRef<std::path::Path>, + actual: impl Into<crate::Data>, +) { + Assert::new() + .action_env(DEFAULT_ACTION_ENV) + .matches_path(pattern_path, actual); +} + +/// Check if a path matches the content of another path, recursively +/// +/// When the content is text, newlines are normalized. +/// +/// ```rust,no_run +/// let output_root = "..."; +/// let expected_root = "tests/snapshots/output.txt"; +/// snapbox::assert_subset_eq(expected_root, output_root); +/// ``` +#[cfg(feature = "path")] +#[track_caller] +pub fn assert_subset_eq( + expected_root: impl Into<std::path::PathBuf>, + actual_root: impl Into<std::path::PathBuf>, +) { + Assert::new() + .action_env(DEFAULT_ACTION_ENV) + .subset_eq(expected_root, actual_root); +} + +/// Check if a path matches the pattern of another path, recursively +/// +/// Pattern syntax: +/// - `...` is a line-wildcard when on a line by itself +/// - `[..]` is a character-wildcard when inside a line +/// - `[EXE]` matches `.exe` on Windows +/// +/// Normalization: +/// - Newlines +/// - `\` to `/` +/// +/// ```rust,no_run +/// let output_root = "..."; +/// let expected_root = "tests/snapshots/output.txt"; +/// snapbox::assert_subset_matches(expected_root, output_root); +/// ``` +#[cfg(feature = "path")] +#[track_caller] +pub fn assert_subset_matches( + pattern_root: impl Into<std::path::PathBuf>, + actual_root: impl Into<std::path::PathBuf>, +) { + Assert::new() + .action_env(DEFAULT_ACTION_ENV) + .subset_matches(pattern_root, actual_root); +} |