use std::path::{Path, PathBuf};
use tempfile::{tempdir, TempDir};
use thiserror::Error;
use touch::file;
pub type Result<T, E = TestFilesError> = core::result::Result<T, E>;
#[derive(Error, Debug)]
pub enum TestFilesError {
#[error("Path error `{path:?}`")]
PathError { path: String },
#[error(transparent)]
FileWriteError(#[from] touch::Error),
#[error(transparent)]
TempDirError(#[from] std::io::Error),
}
pub struct TestFiles(TempDir);
impl TestFiles {
pub fn file(&self, path: &str, content: &str) -> &Self {
self.try_file(path, content).unwrap()
}
pub fn new() -> Self {
Self::try_new().unwrap()
}
pub fn path(&self) -> &Path {
self.0.path()
}
fn slash(&self, relative_path: &str) -> PathBuf {
self.path().join(relative_path)
}
pub fn try_file(&self, path: &str, content: &str) -> Result<&Self> {
file::write(
self.slash(path).to_str().ok_or(TestFilesError::PathError {
path: path.to_string(),
})?,
content,
true,
)?;
Ok(self)
}
pub fn try_new() -> Result<Self> {
Ok(Self(tempdir()?))
}
}
impl Default for TestFiles {
fn default() -> Self {
Self::new()
}
}
#[cfg(test)]
mod tests {
use super::*;
use color_eyre::Result;
use indoc::indoc;
use std::fs;
#[test]
fn makes_deletes_files() -> Result<()> {
let tmp_path: Option<PathBuf>;
{
let files = TestFiles::new();
tmp_path = Some(files.path().to_owned());
let content = indoc! {"
---
version: 3
"};
files.file("a/b/index.yml", content);
let file_path = tmp_path
.as_ref()
.unwrap()
.join("a")
.join("b")
.join("index.yml");
let written_content = fs::read_to_string(file_path).unwrap();
assert_eq!(written_content, content);
}
assert!(!tmp_path.unwrap().is_dir());
Ok(())
}
}