diff --git a/CHANGELOG.md b/CHANGELOG.md index 5a4b0f0b..c7aa9883 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1034,7 +1034,11 @@ This release adds a new fixture to make it easy to create temporary directories Added: - Add a new fixture `temp_dir::create_temp_dir()` to make it easy to create temporary directories for tests. Any temporary directories created are automatically cleaned up - after the test is done. + after the test is done. The `TempDir` struct implements many traits that make it + ergonomic to use with `std::fs`, `std::path` and `std::fmt`. Here are the PRs for this + change: + - [PR 1](https://github.com/r3bl-org/r3bl-open-core/pull/372) + - [PR 2](https://github.com/r3bl-org/r3bl-open-core/pull/373) ### v0.1.0 (2024-10-21) diff --git a/test_fixtures/src/temp_dir.rs b/test_fixtures/src/temp_dir.rs index c25eb447..fd041869 100644 --- a/test_fixtures/src/temp_dir.rs +++ b/test_fixtures/src/temp_dir.rs @@ -15,11 +15,15 @@ * limitations under the License. */ +use std::{fmt::{Display, Formatter}, + ops::Deref, + path::Path}; + use miette::IntoDiagnostic; use r3bl_core::friendly_random_id; pub struct TempDir { - pub path: std::path::PathBuf, + inner: std::path::PathBuf, } /// Create a temporary directory. The directory is automatically deleted when the @@ -28,11 +32,69 @@ pub fn create_temp_dir() -> miette::Result { let root = std::env::temp_dir(); let new_temp_dir = root.join(friendly_random_id::generate_friendly_random_id()); std::fs::create_dir(&new_temp_dir).into_diagnostic()?; - Ok(TempDir { path: new_temp_dir }) + Ok(TempDir { + inner: new_temp_dir, + }) } +/// Automatically delete the temporary directory when the [TempDir] struct is dropped. impl Drop for TempDir { - fn drop(&mut self) { std::fs::remove_dir_all(&self.path).unwrap(); } + fn drop(&mut self) { std::fs::remove_dir_all(&self.inner).unwrap(); } +} + +/// Allow access to the inner [std::path::Path] easily when using other APIs. +/// +/// Implementing the [Deref] trait that exposes the inner [Path] is useful when using +/// other APIs that expect a [Path] instead of a [TempDir], such as: +/// - [std::path::Path::join] +/// +/// # Example +/// +/// ```no_run +/// use r3bl_test_fixtures::create_temp_dir; +/// let root = create_temp_dir().unwrap(); +/// let new_dir = root.join("test_set_file_executable"); +/// ``` +impl Deref for TempDir { + type Target = std::path::PathBuf; + + fn deref(&self) -> &Self::Target { &self.inner } +} + +/// Implement the [Display] trait to allow printing the [TempDir] struct. +/// This is useful when debugging or logging using: +/// - [println!] +/// +/// # Example +/// +/// ```no_run +/// use r3bl_test_fixtures::create_temp_dir; +/// let root = create_temp_dir().unwrap(); +/// println!("Temp dir: {}", root); +/// ``` +impl Display for TempDir { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + write!(f, "{}", self.inner.display()) + } +} + +/// Allow access to the inner [Path] easily when using other APIs. +/// +/// Implementing the [AsRef] trait that exposes the inner [Path] is useful when using +/// other APIs that expect a [Path] instead of a [TempDir], such as: +/// - [std::fs::create_dir_all] +/// - [std::fs::remove_dir_all] +/// +/// # Example +/// +/// ```no_run +/// use r3bl_test_fixtures::create_temp_dir; +/// let root = create_temp_dir().unwrap(); +/// std::fs::create_dir_all(root.join("test_set_file_executable")).unwrap(); +/// std::fs::remove_dir_all(root).unwrap(); +/// ``` +impl AsRef for TempDir { + fn as_ref(&self) -> &Path { &self.inner } } #[cfg(test)] @@ -46,17 +108,17 @@ mod tests { let temp_dir = create_temp_dir().unwrap(); println!( "Temp dir: {}", - temp_dir.path.display().to_string().magenta() + temp_dir.inner.display().to_string().magenta() ); - assert!(temp_dir.path.exists()); + assert!(temp_dir.inner.exists()); } #[test] fn test_temp_dir_drop() { let temp_dir = create_temp_dir().unwrap(); - let copy_of_path = temp_dir.path.clone(); + let copy_of_path = temp_dir.inner.clone(); println!("Temp dir: {}", copy_of_path.display().to_string().magenta()); drop(temp_dir);