use std::path::{Path, PathBuf};
mod common;
use common::{copy_dir, mock_config, run_bin, unique_dir};
fn prepare_repo(tag: &str) -> PathBuf {
let fixture = Path::new(env!("CARGO_MANIFEST_DIR"))
.join("tests")
.join("fixtures")
.join("sample-repo");
let work_dir = unique_dir(tag);
let _ = std::fs::remove_dir_all(&work_dir);
copy_dir(&fixture, &work_dir);
std::fs::write(work_dir.join("config.toml"), mock_config()).unwrap();
work_dir
}
#[test]
fn test_export_skip_generate_after_generate() {
let work_dir = prepare_repo("after_generate");
let out = run_bin(&work_dir, &["generate", "-c", "config.toml"]);
assert!(
out.status.success(),
"generate 应成功,stderr: {}",
String::from_utf8_lossy(&out.stderr)
);
let snapshot = work_dir.join(".code-repo-wiki").join(".state").join("export_snapshot.json");
assert!(snapshot.exists(), "generate 应写导出快照 {}", snapshot.display());
let out = run_bin(&work_dir, &["export", "--skip-generate", "-c", "config.toml"]);
assert!(
out.status.success(),
"export --skip-generate 应成功,stderr: {}",
String::from_utf8_lossy(&out.stderr)
);
assert!(
work_dir.join(".code-repo-wiki").join("index.html").exists(),
"应导出 index.html(目录页)"
);
let _ = std::fs::remove_dir_all(&work_dir);
}
#[test]
fn test_export_skip_generate_missing_snapshot_errors() {
let work_dir = prepare_repo("no_snapshot");
let out = run_bin(&work_dir, &["export", "--skip-generate", "-c", "config.toml"]);
let combined = format!(
"{}{}",
String::from_utf8_lossy(&out.stdout),
String::from_utf8_lossy(&out.stderr)
);
assert!(
!out.status.success(),
"快照缺失时应显式失败,输出: {combined}"
);
assert!(
combined.contains("导出快照不存在"),
"应提示导出快照缺失并引导先运行 generate/update,实际: {combined}"
);
let _ = std::fs::remove_dir_all(&work_dir);
}
#[test]
fn test_export_skip_generate_stale_snapshot_errors() {
let work_dir = prepare_repo("stale_snapshot");
let out = run_bin(&work_dir, &["generate", "-c", "config.toml"]);
assert!(out.status.success(), "generate 应成功: {}", String::from_utf8_lossy(&out.stderr));
let wiki_dir = work_dir.join(".code-repo-wiki").join("wiki").join("zh");
let mut page_mtimes: Vec<(PathBuf, std::time::SystemTime)> = Vec::new();
for entry in std::fs::read_dir(&wiki_dir).unwrap() {
let path = entry.unwrap().path();
if path.extension().is_some_and(|e| e == "md") {
page_mtimes.push((path.clone(), std::fs::metadata(&path).unwrap().modified().unwrap()));
}
}
assert!(!page_mtimes.is_empty(), "生成后应有 wiki 页");
let max_page = page_mtimes.iter().map(|(_, t)| *t).max().unwrap();
let far_future = max_page + std::time::Duration::from_secs(3600);
for (path, _) in &page_mtimes {
std::fs::write(path, format!("{} ", std::fs::read_to_string(path).unwrap())).unwrap();
}
let _ = far_future;
let out = run_bin(&work_dir, &["export", "--skip-generate", "-c", "config.toml"]);
let combined = format!(
"{}{}",
String::from_utf8_lossy(&out.stdout),
String::from_utf8_lossy(&out.stderr)
);
assert!(
!out.status.success(),
"快照过期时应显式失败,输出: {combined}"
);
assert!(
combined.contains("导出快照过期"),
"应提示快照过期并引导重新生成,实际: {combined}"
);
let _ = std::fs::remove_dir_all(&work_dir);
}