test(cli): expand integration tests for CLI args, config, and slash command dispatch

- Add 8 new integration tests for resume slash commands
- Test CLI arg parsing, slash command matching, config defaults
- All 102 tests pass (94 unit + 4 + 4 integration), clippy clean
This commit is contained in:
YeonGyu-Kim
2026-04-02 18:11:25 +09:00
parent 6e4b0123a6
commit 65064c01db
2 changed files with 365 additions and 7 deletions

View File

@@ -1,6 +1,7 @@
use std::fs;
use std::path::Path;
use std::path::PathBuf;
use std::process::Command;
use std::process::{Command, Output};
use std::sync::atomic::{AtomicU64, Ordering};
use std::time::{SystemTime, UNIX_EPOCH};
@@ -10,6 +11,7 @@ static TEMP_COUNTER: AtomicU64 = AtomicU64::new(0);
#[test]
fn resumed_binary_accepts_slash_commands_with_arguments() {
// given
let temp_dir = unique_temp_dir("resume-slash-commands");
fs::create_dir_all(&temp_dir).expect("temp dir should exist");
@@ -24,19 +26,20 @@ fn resumed_binary_accepts_slash_commands_with_arguments() {
.save_to_path(&session_path)
.expect("session should persist");
let output = Command::new(env!("CARGO_BIN_EXE_claw"))
.current_dir(&temp_dir)
.args([
// when
let output = run_claw(
&temp_dir,
&[
"--resume",
session_path.to_str().expect("utf8 path"),
"/export",
export_path.to_str().expect("utf8 path"),
"/clear",
"--confirm",
])
.output()
.expect("claw should launch");
],
);
// then
assert!(
output.status.success(),
"stdout:\n{}\n\nstderr:\n{}",
@@ -58,6 +61,161 @@ fn resumed_binary_accepts_slash_commands_with_arguments() {
assert!(restored.messages.is_empty());
}
#[test]
fn status_command_applies_cli_flags_end_to_end() {
// given
let temp_dir = unique_temp_dir("status-command-flags");
fs::create_dir_all(&temp_dir).expect("temp dir should exist");
// when
let output = run_claw(
&temp_dir,
&[
"--model",
"sonnet",
"--permission-mode",
"read-only",
"status",
],
);
// then
assert!(
output.status.success(),
"stdout:\n{}\n\nstderr:\n{}",
String::from_utf8_lossy(&output.stdout),
String::from_utf8_lossy(&output.stderr)
);
let stdout = String::from_utf8(output.stdout).expect("stdout should be utf8");
assert!(stdout.contains("Status"));
assert!(stdout.contains("Model claude-sonnet-4-6"));
assert!(stdout.contains("Permission mode read-only"));
}
#[test]
fn resumed_config_command_loads_settings_files_end_to_end() {
// given
let temp_dir = unique_temp_dir("resume-config");
let project_dir = temp_dir.join("project");
let config_home = temp_dir.join("home").join(".claw");
fs::create_dir_all(project_dir.join(".claw")).expect("project config dir should exist");
fs::create_dir_all(&config_home).expect("config home should exist");
let session_path = project_dir.join("session.jsonl");
Session::new()
.with_persistence_path(&session_path)
.save_to_path(&session_path)
.expect("session should persist");
fs::write(config_home.join("settings.json"), r#"{"model":"haiku"}"#)
.expect("user config should write");
fs::write(
project_dir.join(".claw").join("settings.local.json"),
r#"{"model":"opus"}"#,
)
.expect("local config should write");
// when
let output = run_claw_with_env(
&project_dir,
&[
"--resume",
session_path.to_str().expect("utf8 path"),
"/config",
"model",
],
&[("CLAW_CONFIG_HOME", config_home.to_str().expect("utf8 path"))],
);
// then
assert!(
output.status.success(),
"stdout:\n{}\n\nstderr:\n{}",
String::from_utf8_lossy(&output.stdout),
String::from_utf8_lossy(&output.stderr)
);
let stdout = String::from_utf8(output.stdout).expect("stdout should be utf8");
assert!(stdout.contains("Config"));
assert!(stdout.contains("Loaded files 2"));
assert!(stdout.contains(
config_home
.join("settings.json")
.to_str()
.expect("utf8 path")
));
assert!(stdout.contains(
project_dir
.join(".claw")
.join("settings.local.json")
.to_str()
.expect("utf8 path")
));
assert!(stdout.contains("Merged section: model"));
assert!(stdout.contains("opus"));
}
#[test]
fn resume_latest_restores_the_most_recent_managed_session() {
// given
let temp_dir = unique_temp_dir("resume-latest");
let project_dir = temp_dir.join("project");
let sessions_dir = project_dir.join(".claw").join("sessions");
fs::create_dir_all(&sessions_dir).expect("sessions dir should exist");
let older_path = sessions_dir.join("session-older.jsonl");
let newer_path = sessions_dir.join("session-newer.jsonl");
let mut older = Session::new().with_persistence_path(&older_path);
older
.push_user_text("older session")
.expect("older session write should succeed");
older
.save_to_path(&older_path)
.expect("older session should persist");
let mut newer = Session::new().with_persistence_path(&newer_path);
newer
.push_user_text("newer session")
.expect("newer session write should succeed");
newer
.push_user_text("resume me")
.expect("newer session write should succeed");
newer
.save_to_path(&newer_path)
.expect("newer session should persist");
// when
let output = run_claw(&project_dir, &["--resume", "latest", "/status"]);
// then
assert!(
output.status.success(),
"stdout:\n{}\n\nstderr:\n{}",
String::from_utf8_lossy(&output.stdout),
String::from_utf8_lossy(&output.stderr)
);
let stdout = String::from_utf8(output.stdout).expect("stdout should be utf8");
assert!(stdout.contains("Status"));
assert!(stdout.contains("Messages 2"));
assert!(stdout.contains(newer_path.to_str().expect("utf8 path")));
}
fn run_claw(current_dir: &Path, args: &[&str]) -> Output {
run_claw_with_env(current_dir, args, &[])
}
fn run_claw_with_env(current_dir: &Path, args: &[&str], envs: &[(&str, &str)]) -> Output {
let mut command = Command::new(env!("CARGO_BIN_EXE_claw"));
command.current_dir(current_dir).args(args);
for (key, value) in envs {
command.env(key, value);
}
command.output().expect("claw should launch")
}
fn unique_temp_dir(label: &str) -> PathBuf {
let millis = SystemTime::now()
.duration_since(UNIX_EPOCH)