use std::fs;
use crate::common::{setup_test_project, run_rsconstruct_with_env};
fn setup_project_with_template() -> tempfile::TempDir {
let temp_dir = setup_test_project();
let project_path = temp_dir.path();
fs::write(
project_path.join("config/test.py"),
"value = 1"
).expect("Failed to write config");
fs::write(
project_path.join("tera.templates/out.txt.tera"),
"{% set c = load_python(path='config/test.py') %}{{ c.value }}"
).expect("Failed to write template");
temp_dir
}
#[test]
fn graph_dot_format() {
let temp_dir = setup_project_with_template();
let project_path = temp_dir.path();
let output = run_rsconstruct_with_env(project_path, &["graph", "show", "--format", "dot"], &[("NO_COLOR", "1")]);
assert!(output.status.success(), "graph --format dot failed: {}", String::from_utf8_lossy(&output.stderr));
let stdout = String::from_utf8_lossy(&output.stdout);
assert!(stdout.contains("digraph"), "Expected DOT digraph in output");
}
#[test]
fn graph_mermaid_format() {
let temp_dir = setup_project_with_template();
let project_path = temp_dir.path();
let output = run_rsconstruct_with_env(project_path, &["graph", "show", "--format", "mermaid"], &[("NO_COLOR", "1")]);
assert!(output.status.success(), "graph --format mermaid failed: {}", String::from_utf8_lossy(&output.stderr));
let stdout = String::from_utf8_lossy(&output.stdout);
assert!(stdout.contains("graph") || stdout.contains("flowchart"),
"Expected mermaid graph syntax in output, got: {}", stdout);
}
#[test]
fn graph_json_format() {
let temp_dir = setup_project_with_template();
let project_path = temp_dir.path();
let output = run_rsconstruct_with_env(project_path, &["graph", "show", "--format", "json"], &[("NO_COLOR", "1")]);
assert!(output.status.success(), "graph --format json failed: {}", String::from_utf8_lossy(&output.stderr));
let stdout = String::from_utf8_lossy(&output.stdout);
assert!(stdout.starts_with('{') || stdout.starts_with('['),
"Expected JSON output, got: {}", stdout);
}
#[test]
fn graph_text_format() {
let temp_dir = setup_project_with_template();
let project_path = temp_dir.path();
let output = run_rsconstruct_with_env(project_path, &["graph", "show", "--format", "text"], &[("NO_COLOR", "1")]);
assert!(output.status.success(), "graph --format text failed: {}", String::from_utf8_lossy(&output.stderr));
let stdout = String::from_utf8_lossy(&output.stdout);
assert!(!stdout.is_empty(), "Expected non-empty text graph output");
}
#[test]
fn graph_empty_project() {
let temp_dir = setup_test_project();
let project_path = temp_dir.path();
let output = run_rsconstruct_with_env(project_path, &["graph", "show", "--format", "json"], &[("NO_COLOR", "1")]);
assert!(output.status.success(), "graph on empty project failed: {}", String::from_utf8_lossy(&output.stderr));
}
#[test]
fn graph_stats() {
let temp_dir = setup_project_with_template();
let project_path = temp_dir.path();
let output = run_rsconstruct_with_env(project_path, &["graph", "stats"], &[("NO_COLOR", "1")]);
assert!(output.status.success(), "graph stats failed: {}", String::from_utf8_lossy(&output.stderr));
let stdout = String::from_utf8_lossy(&output.stdout);
assert!(stdout.contains("products"), "Expected 'products' in stats output, got: {}", stdout);
}
#[test]
fn graph_stats_json() {
let temp_dir = setup_project_with_template();
let project_path = temp_dir.path();
let output = run_rsconstruct_with_env(project_path, &["--json", "graph", "stats"], &[("NO_COLOR", "1")]);
assert!(output.status.success(), "graph stats --json failed: {}", String::from_utf8_lossy(&output.stderr));
let stdout = String::from_utf8_lossy(&output.stdout);
assert!(stdout.starts_with('{'), "Expected JSON output, got: {}", stdout);
}
#[test]
fn graph_unreferenced_finds_untracked_files() {
let temp_dir = tempfile::TempDir::new().unwrap();
let project_path = temp_dir.path();
fs::create_dir(project_path.join("src")).unwrap();
fs::write(project_path.join("rsconstruct.toml"), concat!(
"[processor.script]\n",
"command = \"true\"\n",
"src_extensions = [\".txt\"]\n",
"src_dirs = [\"src\"]\n",
)).unwrap();
fs::write(project_path.join("src/used.txt"), "used\n").unwrap();
fs::write(project_path.join("unused.txt"), "unused\n").unwrap();
run_rsconstruct_with_env(project_path, &["build"], &[("NO_COLOR", "1")]);
let output = run_rsconstruct_with_env(
project_path,
&["graph", "unreferenced", "--extensions", ".txt"],
&[("NO_COLOR", "1")],
);
assert!(output.status.success(), "graph unreferenced failed: {}", String::from_utf8_lossy(&output.stderr));
let stdout = String::from_utf8_lossy(&output.stdout);
assert!(stdout.contains("unused.txt"), "Should report unused.txt: {}", stdout);
assert!(!stdout.contains("src/used.txt"), "Should not report src/used.txt: {}", stdout);
}
#[test]
fn graph_unreferenced_dep_inputs_not_reported() {
let temp_dir = tempfile::TempDir::new().unwrap();
let project_path = temp_dir.path();
fs::create_dir(project_path.join("src")).unwrap();
fs::write(project_path.join("dep.txt"), "dep\n").unwrap();
fs::write(project_path.join("src/source.txt"), "source\n").unwrap();
fs::write(project_path.join("unused.txt"), "unused\n").unwrap();
fs::write(project_path.join("rsconstruct.toml"), concat!(
"[processor.script]\n",
"command = \"true\"\n",
"src_extensions = [\".txt\"]\n",
"src_dirs = [\"src\"]\n",
"dep_inputs = [\"dep.txt\"]\n",
)).unwrap();
run_rsconstruct_with_env(project_path, &["build"], &[("NO_COLOR", "1")]);
let output = run_rsconstruct_with_env(
project_path,
&["graph", "unreferenced", "--extensions", ".txt"],
&[("NO_COLOR", "1")],
);
assert!(output.status.success());
let stdout = String::from_utf8_lossy(&output.stdout);
assert!(!stdout.contains("dep.txt"), "dep.txt is referenced via dep_inputs, should not appear: {}", stdout);
assert!(!stdout.contains("source.txt"), "source.txt is a primary input, should not appear: {}", stdout);
assert!(stdout.contains("unused.txt"), "unused.txt should appear: {}", stdout);
}
#[test]
fn graph_unreferenced_rm_deletes_files() {
let temp_dir = tempfile::TempDir::new().unwrap();
let project_path = temp_dir.path();
fs::create_dir(project_path.join("src")).unwrap();
fs::write(project_path.join("rsconstruct.toml"), concat!(
"[processor.script]\n",
"command = \"true\"\n",
"src_extensions = [\".txt\"]\n",
"src_dirs = [\"src\"]\n",
)).unwrap();
fs::write(project_path.join("src/used.txt"), "used\n").unwrap();
fs::write(project_path.join("unused.txt"), "unused\n").unwrap();
run_rsconstruct_with_env(project_path, &["build"], &[("NO_COLOR", "1")]);
let output = run_rsconstruct_with_env(
project_path,
&["graph", "unreferenced", "--extensions", ".txt", "--rm"],
&[("NO_COLOR", "1")],
);
assert!(output.status.success());
assert!(!project_path.join("unused.txt").exists(), "unused.txt should have been deleted");
assert!(project_path.join("src/used.txt").exists(), "src/used.txt should still exist");
}