mod common;
use assert_cmd::Command;
use common::TempProject;
use predicates::prelude::*;
#[allow(deprecated)]
fn vyctor() -> Command {
Command::cargo_bin("vyctor").unwrap()
}
#[test]
fn test_cli_help() {
vyctor()
.arg("--help")
.assert()
.success()
.stdout(predicate::str::contains("semantic file search"))
.stdout(predicate::str::contains("init"))
.stdout(predicate::str::contains("lookup"))
.stdout(predicate::str::contains("sync"))
.stdout(predicate::str::contains("watch"))
.stdout(predicate::str::contains("status"));
}
#[test]
fn test_cli_version() {
vyctor()
.arg("--version")
.assert()
.success()
.stdout(predicate::str::contains("vyctor"));
}
#[test]
fn test_init_help() {
vyctor()
.args(["init", "--help"])
.assert()
.success()
.stdout(predicate::str::contains("Initialize"));
}
#[test]
fn test_lookup_help() {
vyctor()
.args(["lookup", "--help"])
.assert()
.success()
.stdout(predicate::str::contains("Search"));
}
#[test]
fn test_sync_help() {
vyctor()
.args(["sync", "--help"])
.assert()
.success()
.stdout(predicate::str::contains("Synchronize"));
}
#[test]
fn test_status_help() {
vyctor().args(["status", "--help"]).assert().success();
}
#[test]
fn test_config_help() {
vyctor().args(["config", "--help"]).assert().success();
}
#[test]
fn test_init_creates_config_directory() {
let project = TempProject::new();
vyctor()
.current_dir(project.path())
.arg("init")
.assert()
.success()
.stdout(predicate::str::contains("vyctor.config.toml"));
assert!(project.file_exists("vyctor.config.toml"));
}
#[test]
fn test_init_creates_gitignore() {
let project = TempProject::new();
vyctor()
.current_dir(project.path())
.arg("init")
.assert()
.success();
assert!(project.file_exists(".gitignore"));
let gitignore = project.read_file(".gitignore");
assert!(gitignore.contains(".vyctor"));
}
#[test]
fn test_init_updates_existing_gitignore() {
let project = TempProject::new();
project.create_file(".gitignore", "node_modules/\n*.log\n");
vyctor()
.current_dir(project.path())
.arg("init")
.assert()
.success();
let gitignore = project.read_file(".gitignore");
assert!(gitignore.contains("node_modules/"));
assert!(gitignore.contains("*.log"));
assert!(gitignore.contains(".vyctor"));
}
#[test]
fn test_init_fails_if_already_exists() {
let project = TempProject::new();
vyctor()
.current_dir(project.path())
.arg("init")
.assert()
.success();
vyctor()
.current_dir(project.path())
.arg("init")
.assert()
.failure()
.stderr(predicate::str::contains("already exists"));
}
#[test]
fn test_init_force_reinitializes() {
let project = TempProject::new();
vyctor()
.current_dir(project.path())
.arg("init")
.assert()
.success();
project.create_file("vyctor.config.toml", "# Modified config");
vyctor()
.current_dir(project.path())
.args(["init", "--force"])
.assert()
.success();
let config = project.read_file("vyctor.config.toml");
assert!(config.contains("[indexing]"));
assert!(config.contains("[embedding]"));
}
#[test]
fn test_status_without_init() {
let project = TempProject::new();
vyctor()
.current_dir(project.path())
.arg("status")
.assert()
.failure()
.stderr(predicate::str::contains("vyctor.config.toml"));
}
#[test]
fn test_status_after_init() {
let project = TempProject::new();
vyctor()
.current_dir(project.path())
.arg("init")
.assert()
.success();
vyctor()
.current_dir(project.path())
.arg("status")
.assert()
.success()
.stdout(predicate::str::contains("Configuration"));
}
#[test]
fn test_lookup_without_init() {
let project = TempProject::new();
vyctor()
.current_dir(project.path())
.args(["lookup", "test query"])
.assert()
.failure();
}
#[test]
fn test_sync_without_init() {
let project = TempProject::new();
vyctor()
.current_dir(project.path())
.arg("sync")
.assert()
.failure();
}
#[test]
fn test_config_without_init() {
let project = TempProject::new();
vyctor()
.current_dir(project.path())
.arg("config")
.assert()
.failure();
}
#[test]
fn test_config_shows_config() {
let project = TempProject::new();
vyctor()
.current_dir(project.path())
.arg("init")
.assert()
.success();
vyctor()
.current_dir(project.path())
.arg("config")
.assert()
.success()
.stdout(predicate::str::contains("[indexing]"))
.stdout(predicate::str::contains("[embedding]"));
}
#[test]
fn test_init_shows_configuration_summary() {
let project = TempProject::new();
vyctor()
.current_dir(project.path())
.arg("init")
.assert()
.success()
.stdout(predicate::str::contains("Embedding provider"))
.stdout(predicate::str::contains("Chunk size"));
}
#[test]
fn test_lookup_count_flag() {
let project = TempProject::new();
project.init_vyctor();
vyctor()
.current_dir(project.path())
.args(["lookup", "test", "-n", "10"])
.assert()
.stderr(
predicate::str::contains("")
.not()
.or(predicate::str::contains("")),
);
}
#[test]
fn test_lookup_folder_flag() {
let project = TempProject::new();
project.init_vyctor();
let _ = vyctor()
.current_dir(project.path())
.args(["lookup", "test", "--folder", "src/"])
.assert();
}
#[test]
fn test_sync_force_flag() {
let project = TempProject::new();
project.init_vyctor();
let _ = vyctor()
.current_dir(project.path())
.args(["sync", "--force"])
.assert();
}
#[test]
fn test_init_from_subdirectory() {
let project = TempProject::new();
project.create_dir("src/nested");
vyctor()
.current_dir(project.path())
.arg("init")
.assert()
.success();
vyctor()
.current_dir(project.path().join("src/nested"))
.arg("status")
.assert()
.success();
}
#[test]
fn test_config_file_format() {
let project = TempProject::new();
vyctor()
.current_dir(project.path())
.arg("init")
.assert()
.success();
let config = project.read_file("vyctor.config.toml");
let parsed: toml::Value = toml::from_str(&config).expect("Config should be valid TOML");
assert!(
parsed.get("indexing").is_some(),
"Should have [indexing] section"
);
assert!(
parsed.get("embedding").is_some(),
"Should have [embedding] section"
);
}
#[test]
fn test_invalid_command() {
vyctor().arg("nonexistent").assert().failure();
}
#[test]
fn test_lookup_requires_query() {
let project = TempProject::new();
project.init_vyctor();
vyctor()
.current_dir(project.path())
.arg("lookup")
.assert()
.failure();
}
#[test]
fn test_full_workflow_with_vss() {
if !common::vss_available() {
eprintln!("Skipping test: VSS extension not available");
return;
}
let project = TempProject::with_sample_files();
vyctor()
.current_dir(project.path())
.arg("init")
.assert()
.success();
vyctor()
.current_dir(project.path())
.arg("status")
.assert()
.success();
}