use std::collections::HashMap;
use std::fs;
use std::path::{Path, PathBuf};
pub struct FixtureRepo {
pub name: String,
pub path: PathBuf,
pub files: HashMap<PathBuf, FixtureFile>,
}
pub struct FixtureFile {
pub path: PathBuf,
pub content: String,
pub language: String,
}
impl FixtureRepo {
pub fn new(name: &str, path: PathBuf) -> Self {
Self {
name: name.to_string(),
path,
files: HashMap::new(),
}
}
pub fn load(&mut self) -> std::io::Result<()> {
if !self.path.exists() {
return Ok(());
}
for entry in walkdir::WalkDir::new(&self.path)
.into_iter()
.filter_map(|e| e.ok())
{
if entry.file_type().is_file() {
if let Ok(content) = fs::read_to_string(entry.path()) {
let language = detect_language(entry.path());
self.files.insert(
entry.path().to_path_buf(),
FixtureFile {
path: entry.path().to_path_buf(),
content,
language,
},
);
}
}
}
Ok(())
}
pub fn get_file(&self, relative: &str) -> Option<&FixtureFile> {
let path = self.path.join(relative);
self.files.get(&path)
}
pub fn list_files(&self) -> Vec<&FixtureFile> {
self.files.values().collect()
}
}
fn detect_language(path: &Path) -> String {
match path.extension().and_then(|e| e.to_str()) {
Some("js") => "javascript".to_string(),
Some("jsx") => "javascript".to_string(),
Some("ts") => "typescript".to_string(),
Some("tsx") => "typescript".to_string(),
Some("json") => "json".to_string(),
Some("md") => "markdown".to_string(),
Some("rs") => "rust".to_string(),
_ => "unknown".to_string(),
}
}
pub fn load_fixture_repo(name: &str, fixtures_path: &Path) -> Option<FixtureRepo> {
let repo_path = fixtures_path.join(name);
if !repo_path.exists() {
return None;
}
let mut repo = FixtureRepo::new(name, repo_path);
repo.load().ok()?;
Some(repo)
}
pub fn list_fixture_repos(fixtures_path: &Path) -> Vec<String> {
let mut repos = Vec::new();
if let Ok(entries) = fs::read_dir(fixtures_path) {
for entry in entries.filter_map(|e| e.ok()) {
if entry.path().is_dir() {
if let Some(name) = entry.path().file_name().and_then(|n| n.to_str()) {
repos.push(name.to_string());
}
}
}
}
repos
}
#[cfg(test)]
mod tests {
use super::*;
use tempfile::TempDir;
#[test]
fn test_fixture_repo_new() {
let dir = TempDir::new().unwrap();
let repo = FixtureRepo::new("test", dir.path().to_path_buf());
assert_eq!(repo.name, "test");
assert!(repo.files.is_empty());
}
#[test]
fn test_detect_language_js() {
let path = Path::new("test.js");
assert_eq!(detect_language(path), "javascript");
}
#[test]
fn test_detect_language_ts() {
let path = Path::new("test.ts");
assert_eq!(detect_language(path), "typescript");
}
#[test]
fn test_detect_language_unknown() {
let path = Path::new("test.xyz");
assert_eq!(detect_language(path), "unknown");
}
#[test]
fn test_list_fixture_repos_empty() {
let dir = TempDir::new().unwrap();
let repos = list_fixture_repos(dir.path());
assert!(repos.is_empty());
}
}