use assert_cmd::Command;
use predicates::prelude::PredicateBooleanExt;
use predicates::str::contains;
use std::path::{Path, PathBuf};
use tempfile::TempDir;
const TS_FIXTURE: &str = "tests/fixtures/typescript-simple";
fn copy_dir_all(src: &Path, dest: &Path) {
std::fs::create_dir_all(dest).unwrap();
for entry in std::fs::read_dir(src).unwrap() {
let entry = entry.unwrap();
let src_path = entry.path();
let dest_path = dest.join(entry.file_name());
if src_path.is_dir() {
copy_dir_all(&src_path, &dest_path);
} else {
std::fs::copy(&src_path, &dest_path).unwrap();
}
}
}
fn setup_indexed_fixture() -> (TempDir, PathBuf) {
let dir = TempDir::new().unwrap();
let fixture = Path::new(TS_FIXTURE);
copy_dir_all(fixture, dir.path());
Command::cargo_bin("scope")
.unwrap()
.arg("init")
.current_dir(dir.path())
.assert()
.success();
Command::cargo_bin("scope")
.unwrap()
.args(["index", "--full"])
.current_dir(dir.path())
.assert()
.success();
let root = dir.path().to_path_buf();
(dir, root)
}
#[test]
fn test_flow_finds_path_between_connected_symbols() {
let (_dir, root) = setup_indexed_fixture();
Command::cargo_bin("scope")
.unwrap()
.args(["flow", "processPayment", "validateAmount"])
.current_dir(&root)
.assert()
.success()
.stdout(contains("processPayment").and(contains("validateAmount")));
}
#[test]
fn test_flow_returns_no_path_when_symbols_unconnected() {
let (_dir, root) = setup_indexed_fixture();
let output = Command::cargo_bin("scope")
.unwrap()
.args(["flow", "processPayment", "Logger"])
.current_dir(&root)
.output()
.unwrap();
assert!(
output.status.success(),
"flow with no path should exit 0, not crash"
);
}
#[test]
fn test_flow_json_output_structure() {
let (_dir, root) = setup_indexed_fixture();
let output = Command::cargo_bin("scope")
.unwrap()
.args(["flow", "processPayment", "validateAmount", "--json"])
.current_dir(&root)
.assert()
.success()
.get_output()
.stdout
.clone();
let json: serde_json::Value =
serde_json::from_slice(&output).expect("flow --json should produce valid JSON");
assert_eq!(
json["command"], "flow",
"JSON envelope should have command = 'flow'; got: {}",
json["command"]
);
let data = &json["data"];
assert!(
data["start"].is_string(),
"data.start should be a string; got: {}",
data["start"]
);
assert!(
data["end"].is_string(),
"data.end should be a string; got: {}",
data["end"]
);
assert!(
data["paths"].is_array(),
"data.paths should be an array; got: {}",
data["paths"]
);
assert_eq!(
data["start"], "processPayment",
"data.start should be 'processPayment'"
);
assert_eq!(
data["end"], "validateAmount",
"data.end should be 'validateAmount'"
);
}
#[test]
fn test_flow_unknown_symbol_fails_with_not_found() {
let (_dir, root) = setup_indexed_fixture();
Command::cargo_bin("scope")
.unwrap()
.args(["flow", "NonExistentSymbol", "AlsoNonExistent"])
.current_dir(&root)
.assert()
.failure()
.code(1)
.stderr(contains("not found"));
}