use std::fs;
use flowmark::skills::{get_docs_content, get_skill_content, install_skill};
#[test]
fn test_skill_content_loads() {
let content = get_skill_content();
assert!(!content.is_empty(), "SKILL.md should be loadable and non-empty");
}
#[test]
fn test_skill_content_has_metadata() {
let content = get_skill_content();
assert!(content.contains("name: flowmark"), "should contain name: flowmark");
assert!(content.contains("description:"), "should contain description:");
assert!(content.contains("allowed-tools:"), "should contain allowed-tools:");
}
#[test]
fn test_skill_content_has_usage() {
let content = get_skill_content();
assert!(content.contains("# Flowmark"), "should contain # Flowmark heading");
assert!(content.contains("flowmark --auto"), "should contain usage instructions");
}
#[test]
fn test_skill_content_has_vscode_cursor_setup() {
let content = get_skill_content();
assert!(
content.contains("VS Code/Cursor"),
"skill should include VS Code/Cursor setup section"
);
assert!(
content.contains("emeraldwalk.runonsave"),
"skill should include run-on-save configuration"
);
}
#[test]
fn test_docs_content_loads() {
let content = get_docs_content();
assert!(!content.is_empty(), "docs content should be non-empty");
}
#[test]
fn test_docs_content_has_flowmark_reference() {
let content = get_docs_content();
let lower = content.to_lowercase();
assert!(lower.contains("flowmark"), "docs content should reference flowmark");
}
#[test]
fn test_docs_content_has_vscode_cursor_setup() {
let content = get_docs_content();
assert!(
content.contains("VSCode/Cursor") || content.contains("VS Code/Cursor"),
"docs should include VS Code/Cursor section"
);
assert!(
content.contains("emeraldwalk.runonsave"),
"docs should include run-on-save settings snippet"
);
}
#[test]
fn test_install_skill_default() {
let dir = tempfile::tempdir().expect("create temp dir");
let base = dir.path().join(".claude");
install_skill(Some(base.to_str().expect("path to str"))).expect("install skill");
let skill_file = base.join("skills").join("flowmark").join("SKILL.md");
assert!(skill_file.exists(), "SKILL.md should be created");
let content = fs::read_to_string(&skill_file).expect("read SKILL.md");
assert!(content.contains("name: flowmark"), "should contain name: flowmark");
}
#[test]
fn test_install_skill_custom_base() {
let dir = tempfile::tempdir().expect("create temp dir");
let custom_base = dir.path().join(".claude");
install_skill(Some(custom_base.to_str().expect("path to str"))).expect("install skill");
let skill_file = custom_base.join("skills").join("flowmark").join("SKILL.md");
assert!(skill_file.exists(), "SKILL.md should be created at custom base");
let content = fs::read_to_string(&skill_file).expect("read SKILL.md");
assert!(content.contains("name: flowmark"), "should contain name: flowmark");
}
#[test]
fn test_install_skill_creates_directories() {
let dir = tempfile::tempdir().expect("create temp dir");
let custom_base = dir.path().join("deep").join("nested").join("path");
install_skill(Some(custom_base.to_str().expect("path to str"))).expect("install skill");
let skill_file = custom_base.join("skills").join("flowmark").join("SKILL.md");
assert!(skill_file.exists(), "SKILL.md should be created in deeply nested path");
}
#[test]
fn test_install_skill_overwrites_existing() {
let dir = tempfile::tempdir().expect("create temp dir");
let custom_base = dir.path().join(".claude");
let skill_dir = custom_base.join("skills").join("flowmark");
fs::create_dir_all(&skill_dir).expect("create skill dir");
let skill_file = skill_dir.join("SKILL.md");
fs::write(&skill_file, "old content").expect("write old content");
install_skill(Some(custom_base.to_str().expect("path to str"))).expect("install skill");
let content = fs::read_to_string(&skill_file).expect("read SKILL.md");
assert!(!content.contains("old content"), "old content should be overwritten");
assert!(content.contains("name: flowmark"), "should contain name: flowmark");
}
#[test]
fn test_install_skill_rejects_path_traversal() {
let result = install_skill(Some("../../tmp/evil"));
assert!(result.is_err(), "path traversal should be rejected");
let err = result.expect_err("should error");
assert!(err.contains(".."), "error message should mention '..' traversal: {err}");
}
#[test]
fn test_install_skill_safe_relative_path() {
let dir = tempfile::tempdir().expect("create temp dir");
let safe_path = dir.path().join("project").join(".claude");
install_skill(Some(safe_path.to_str().expect("path to str"))).expect("install skill");
assert!(safe_path.join("skills/flowmark/SKILL.md").exists());
}