Changes slash command directory from `.claude/commands/` to `.owlen/commands/` to reflect that owlen is its own tool while maintaining compatibility with claude-code slash command syntax. Updated locations: - CLI main: command file path lookup - Tests: slash_command_works and slash_command_file_refs All 56 tests passing.
256 lines
7.3 KiB
Rust
256 lines
7.3 KiB
Rust
use assert_cmd::Command;
|
|
use std::fs;
|
|
use tempfile::tempdir;
|
|
|
|
#[test]
|
|
fn plan_mode_allows_read_operations() {
|
|
// Create a temp file to read
|
|
let dir = tempdir().unwrap();
|
|
let file = dir.path().join("test.txt");
|
|
fs::write(&file, "hello world").unwrap();
|
|
|
|
// Read operation should work in plan mode (default)
|
|
let mut cmd = Command::new(assert_cmd::cargo::cargo_bin!("owlen"));
|
|
cmd.arg("read").arg(file.to_str().unwrap());
|
|
cmd.assert().success().stdout("hello world\n");
|
|
}
|
|
|
|
#[test]
|
|
fn plan_mode_allows_glob_operations() {
|
|
let dir = tempdir().unwrap();
|
|
fs::write(dir.path().join("a.txt"), "test").unwrap();
|
|
fs::write(dir.path().join("b.txt"), "test").unwrap();
|
|
|
|
let pattern = format!("{}/*.txt", dir.path().display());
|
|
|
|
// Glob operation should work in plan mode (default)
|
|
let mut cmd = Command::new(assert_cmd::cargo::cargo_bin!("owlen"));
|
|
cmd.arg("glob").arg(&pattern);
|
|
cmd.assert().success();
|
|
}
|
|
|
|
#[test]
|
|
fn plan_mode_allows_grep_operations() {
|
|
let dir = tempdir().unwrap();
|
|
fs::write(dir.path().join("test.txt"), "hello world\nfoo bar").unwrap();
|
|
|
|
// Grep operation should work in plan mode (default)
|
|
let mut cmd = Command::new(assert_cmd::cargo::cargo_bin!("owlen"));
|
|
cmd.arg("grep").arg(dir.path().to_str().unwrap()).arg("hello");
|
|
cmd.assert().success();
|
|
}
|
|
|
|
#[test]
|
|
fn mode_override_via_cli_flag() {
|
|
let dir = tempdir().unwrap();
|
|
let file = dir.path().join("test.txt");
|
|
fs::write(&file, "content").unwrap();
|
|
|
|
// Test with --mode code (should also allow read)
|
|
let mut cmd = Command::new(assert_cmd::cargo::cargo_bin!("owlen"));
|
|
cmd.arg("--mode")
|
|
.arg("code")
|
|
.arg("read")
|
|
.arg(file.to_str().unwrap());
|
|
cmd.assert().success().stdout("content\n");
|
|
}
|
|
|
|
#[test]
|
|
fn plan_mode_blocks_write_operations() {
|
|
let dir = tempdir().unwrap();
|
|
let file = dir.path().join("new.txt");
|
|
|
|
// Write operation should be blocked in plan mode (default)
|
|
let mut cmd = Command::new(assert_cmd::cargo::cargo_bin!("owlen"));
|
|
cmd.arg("write").arg(file.to_str().unwrap()).arg("content");
|
|
cmd.assert().failure();
|
|
}
|
|
|
|
#[test]
|
|
fn plan_mode_blocks_edit_operations() {
|
|
let dir = tempdir().unwrap();
|
|
let file = dir.path().join("test.txt");
|
|
fs::write(&file, "old content").unwrap();
|
|
|
|
// Edit operation should be blocked in plan mode (default)
|
|
let mut cmd = Command::new(assert_cmd::cargo::cargo_bin!("owlen"));
|
|
cmd.arg("edit")
|
|
.arg(file.to_str().unwrap())
|
|
.arg("old")
|
|
.arg("new");
|
|
cmd.assert().failure();
|
|
}
|
|
|
|
#[test]
|
|
fn accept_edits_mode_allows_write() {
|
|
let dir = tempdir().unwrap();
|
|
let file = dir.path().join("new.txt");
|
|
|
|
// Write operation should work in acceptEdits mode
|
|
let mut cmd = Command::new(assert_cmd::cargo::cargo_bin!("owlen"));
|
|
cmd.arg("--mode")
|
|
.arg("acceptEdits")
|
|
.arg("write")
|
|
.arg(file.to_str().unwrap())
|
|
.arg("new content");
|
|
cmd.assert().success();
|
|
|
|
// Verify file was written
|
|
assert_eq!(fs::read_to_string(&file).unwrap(), "new content");
|
|
}
|
|
|
|
#[test]
|
|
fn accept_edits_mode_allows_edit() {
|
|
let dir = tempdir().unwrap();
|
|
let file = dir.path().join("test.txt");
|
|
fs::write(&file, "line 1\nline 2\nline 3").unwrap();
|
|
|
|
// Edit operation should work in acceptEdits mode
|
|
let mut cmd = Command::new(assert_cmd::cargo::cargo_bin!("owlen"));
|
|
cmd.arg("--mode")
|
|
.arg("acceptEdits")
|
|
.arg("edit")
|
|
.arg(file.to_str().unwrap())
|
|
.arg("line 2")
|
|
.arg("modified line");
|
|
cmd.assert().success();
|
|
|
|
// Verify file was edited
|
|
assert_eq!(
|
|
fs::read_to_string(&file).unwrap(),
|
|
"line 1\nmodified line\nline 3"
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn code_mode_allows_all_operations() {
|
|
let dir = tempdir().unwrap();
|
|
let file = dir.path().join("test.txt");
|
|
|
|
// Write in code mode
|
|
let mut cmd = Command::new(assert_cmd::cargo::cargo_bin!("owlen"));
|
|
cmd.arg("--mode")
|
|
.arg("code")
|
|
.arg("write")
|
|
.arg(file.to_str().unwrap())
|
|
.arg("initial content");
|
|
cmd.assert().success();
|
|
|
|
// Edit in code mode
|
|
let mut cmd = Command::new(assert_cmd::cargo::cargo_bin!("owlen"));
|
|
cmd.arg("--mode")
|
|
.arg("code")
|
|
.arg("edit")
|
|
.arg(file.to_str().unwrap())
|
|
.arg("initial")
|
|
.arg("modified");
|
|
cmd.assert().success();
|
|
|
|
assert_eq!(fs::read_to_string(&file).unwrap(), "modified content");
|
|
}
|
|
|
|
#[test]
|
|
fn plan_mode_blocks_bash_operations() {
|
|
// Bash operation should be blocked in plan mode (default)
|
|
let mut cmd = Command::new(assert_cmd::cargo::cargo_bin!("owlen"));
|
|
cmd.arg("bash").arg("echo hello");
|
|
cmd.assert().failure();
|
|
}
|
|
|
|
#[test]
|
|
fn code_mode_allows_bash() {
|
|
// Bash operation should work in code mode
|
|
let mut cmd = Command::new(assert_cmd::cargo::cargo_bin!("owlen"));
|
|
cmd.arg("--mode").arg("code").arg("bash").arg("echo hello");
|
|
cmd.assert().success().stdout("hello\n");
|
|
}
|
|
|
|
#[test]
|
|
fn bash_command_timeout_works() {
|
|
// Test that timeout works
|
|
let mut cmd = Command::new(assert_cmd::cargo::cargo_bin!("owlen"));
|
|
cmd.arg("--mode")
|
|
.arg("code")
|
|
.arg("bash")
|
|
.arg("sleep 10")
|
|
.arg("--timeout")
|
|
.arg("1000");
|
|
cmd.assert().failure();
|
|
}
|
|
|
|
#[test]
|
|
fn slash_command_works() {
|
|
// Create .owlen/commands directory in temp dir
|
|
let dir = tempdir().unwrap();
|
|
let commands_dir = dir.path().join(".owlen/commands");
|
|
fs::create_dir_all(&commands_dir).unwrap();
|
|
|
|
// Create a test slash command
|
|
let command_content = r#"---
|
|
description: "Test command"
|
|
---
|
|
Hello from slash command!
|
|
Args: $ARGUMENTS
|
|
First: $1
|
|
"#;
|
|
let command_file = commands_dir.join("test.md");
|
|
fs::write(&command_file, command_content).unwrap();
|
|
|
|
// Execute slash command with args from the temp directory
|
|
let mut cmd = Command::new(assert_cmd::cargo::cargo_bin!("owlen"));
|
|
cmd.current_dir(dir.path())
|
|
.arg("--mode")
|
|
.arg("code")
|
|
.arg("slash")
|
|
.arg("test")
|
|
.arg("arg1");
|
|
|
|
cmd.assert()
|
|
.success()
|
|
.stdout(predicates::str::contains("Hello from slash command!"))
|
|
.stdout(predicates::str::contains("Args: arg1"))
|
|
.stdout(predicates::str::contains("First: arg1"));
|
|
}
|
|
|
|
#[test]
|
|
fn slash_command_file_refs() {
|
|
let dir = tempdir().unwrap();
|
|
let commands_dir = dir.path().join(".owlen/commands");
|
|
fs::create_dir_all(&commands_dir).unwrap();
|
|
|
|
// Create a file to reference
|
|
let data_file = dir.path().join("data.txt");
|
|
fs::write(&data_file, "Referenced content").unwrap();
|
|
|
|
// Create slash command with file reference
|
|
let command_content = format!("File content: @{}", data_file.display());
|
|
fs::write(commands_dir.join("reftest.md"), command_content).unwrap();
|
|
|
|
// Execute slash command
|
|
let mut cmd = Command::new(assert_cmd::cargo::cargo_bin!("owlen"));
|
|
cmd.current_dir(dir.path())
|
|
.arg("--mode")
|
|
.arg("code")
|
|
.arg("slash")
|
|
.arg("reftest");
|
|
|
|
cmd.assert()
|
|
.success()
|
|
.stdout(predicates::str::contains("Referenced content"));
|
|
}
|
|
|
|
#[test]
|
|
fn slash_command_not_found() {
|
|
let dir = tempdir().unwrap();
|
|
|
|
// Try to execute non-existent slash command
|
|
let mut cmd = Command::new(assert_cmd::cargo::cargo_bin!("owlen"));
|
|
cmd.current_dir(dir.path())
|
|
.arg("--mode")
|
|
.arg("code")
|
|
.arg("slash")
|
|
.arg("nonexistent");
|
|
|
|
cmd.assert().failure();
|
|
}
|