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(); }