mod common;
use predicates::prelude::*;
use common::TestProject;
#[test]
fn add_local_path_installs_to_canonical() {
let p = TestProject::new();
let src = p.write_skill_source("my-skill", "pdf");
p.skills()
.args(["add", src.to_str().unwrap(), "--project", "."])
.assert()
.success()
.stdout(predicate::str::contains("Installed 1 skill"));
p.assert_exists(".agents/skills/pdf/SKILL.md");
p.assert_exists("skills-lock.json");
assert!(p.read("skills-lock.json").contains("\"pdf\""));
}
#[test]
fn subcommand_aliases_are_rejected() {
let p = TestProject::new();
let src = p.write_skill_source("my-skill", "pdf");
for alias in [
"a", "i", "install", "rm", "r", "ls", "d", "e", "upgrade", "check",
] {
p.skills()
.args([alias, src.to_str().unwrap()])
.assert()
.failure()
.stdout(predicate::str::contains("Unknown command"));
}
p.assert_absent(".agents/skills/pdf");
}
#[test]
fn add_list_flag_prints_without_installing() {
let p = TestProject::new();
let src = p.write_skill_source("my-skill", "pdf");
p.skills()
.arg("add")
.arg(&src)
.arg("--list")
.assert()
.success()
.stdout(predicate::str::contains("Available Skills"))
.stdout(predicate::str::contains("pdf"));
p.assert_absent(".agents/skills/pdf");
}
#[test]
fn add_missing_local_path_exits_nonzero() {
let p = TestProject::new();
let missing = p.path().join("does-not-exist");
p.skills()
.args(["add", missing.to_str().unwrap()])
.assert()
.failure()
.code(1)
.stdout(predicate::str::contains("Local path does not exist"));
}
#[test]
fn add_global_installs_to_home() {
let p = TestProject::new();
let home = p.path().join("home");
std::fs::create_dir_all(&home).unwrap();
let src = p.write_skill_source("my-skill", "pdf");
p.skills()
.env("HOME", &home)
.args(["add", src.to_str().unwrap()])
.assert()
.success()
.stdout(predicate::str::contains("Installed 1 skill"));
assert!(home.join(".agents/skills/pdf/SKILL.md").exists());
p.assert_absent(".agents/skills/pdf");
}
#[test]
fn add_project_dir_flag_installs_into_given_dir() {
let p = TestProject::new();
let home = p.path().join("home");
std::fs::create_dir_all(&home).unwrap();
let target = p.path().join("other-project");
std::fs::create_dir_all(&target).unwrap();
let src = p.write_skill_source("my-skill", "pdf");
p.skills()
.env("HOME", &home)
.args([
"add",
src.to_str().unwrap(),
"--project",
target.to_str().unwrap(),
])
.assert()
.success()
.stdout(predicate::str::contains("Installed 1 skill"));
assert!(target.join(".agents/skills/pdf/SKILL.md").exists());
p.assert_absent(".agents/skills/pdf");
assert!(!home.join(".agents/skills/pdf").exists());
}
#[test]
fn add_project_dir_must_exist() {
let p = TestProject::new();
let src = p.write_skill_source("my-skill", "pdf");
p.skills()
.args(["add", src.to_str().unwrap(), "--project", "no-such-dir"])
.assert()
.failure()
.code(1)
.stderr(predicate::str::contains("project directory not found"));
p.assert_absent(".agents/skills/pdf");
}
#[test]
fn full_depth_flag_is_rejected() {
let p = TestProject::new();
p.skills()
.args(["add", p.path().to_str().unwrap(), "--full-depth"])
.assert()
.failure()
.stderr(predicate::str::contains("unexpected argument"));
}
#[test]
fn add_installs_every_source_argument() {
let p = TestProject::new();
let a = p.write_skill_source("src-a", "alpha");
let b = p.write_skill_source("src-b", "beta");
p.skills()
.args([
"add",
a.to_str().unwrap(),
b.to_str().unwrap(),
"--project",
".",
])
.assert()
.success()
.stdout(predicate::str::contains("Installed 1 skill"));
p.assert_exists(".agents/skills/alpha/SKILL.md");
p.assert_exists(".agents/skills/beta/SKILL.md");
}