use std::fs;
use std::path::Path;
use std::process::Command;
use tempfile::TempDir;
use walkdir::WalkDir;
#[test]
fn binary_generates_expected_catalog_from_fixture() {
let fixture = Path::new("examples/manual-e2e-fixture");
assert!(fixture.exists(), "fixture folder must exist");
let temp = TempDir::new().expect("create temp dir");
copy_dir_all(fixture, temp.path());
let binary = env!("CARGO_BIN_EXE_taskc");
let output = Command::new(binary)
.current_dir(temp.path())
.output()
.expect("run taskc binary");
assert!(output.status.success(), "binary should exit successfully");
let stdout = String::from_utf8(output.stdout).expect("utf8 stdout");
assert!(
stdout.contains("Generated 3 tasks from 4 markdown files"),
"stdout was: {stdout}"
);
let html_path = temp.path().join("tasks.html");
assert!(html_path.exists(), "tasks.html should be generated");
let html = fs::read_to_string(&html_path).expect("read generated html");
assert!(html.contains("Root task: onboarding"));
assert!(html.contains("App task: release checklist"));
assert!(html.contains("Docs task: write guide"));
assert!(!html.contains("Ignored node_modules task"));
assert!(!html.contains("Ignored target task"));
assert!(!html.contains("Ignored hidden task"));
assert!(html.contains("Markdown files scanned: 4"));
assert!(html.contains("Tasks: 3"));
assert!(html.contains("id=\"toggle-collapse\""));
assert!(html.contains("id=\"toggle-theme\""));
assert!(html.contains("<details class=\"task-card\""));
assert!(html.contains("<body data-theme=\"dark\">"));
assert!(
html.contains("<ul>"),
"markdown list should render as HTML list"
);
assert!(
html.contains("Nested detail"),
"deeper header should remain in the captured task body"
);
assert!(
!html.contains("Unmarked heading"),
"same-level unmarked header should terminate task body"
);
}
fn copy_dir_all(src: &Path, dst: &Path) {
for entry in WalkDir::new(src).into_iter().filter_map(Result::ok) {
let path = entry.path();
let rel = path
.strip_prefix(src)
.expect("entry path should be inside source");
if rel.as_os_str().is_empty() {
continue;
}
let target = dst.join(rel);
if entry.file_type().is_dir() {
fs::create_dir_all(&target).expect("create dir");
} else {
if let Some(parent) = target.parent() {
fs::create_dir_all(parent).expect("create parent");
}
fs::copy(path, &target).expect("copy file");
}
}
}