use super::*;
#[test]
fn test_parse_empty_is_list_changed() {
assert_eq!(parse_set_expr(""), SetAction::ListChanged);
}
#[test]
fn test_parse_whitespace_only_is_list_changed() {
assert_eq!(parse_set_expr(" "), SetAction::ListChanged);
}
#[test]
fn test_parse_all_is_list_all() {
assert_eq!(parse_set_expr("all"), SetAction::ListAll);
}
#[test]
fn test_parse_query() {
assert_eq!(
parse_set_expr("number?"),
SetAction::Show {
name: "number".to_string()
}
);
}
#[test]
fn test_parse_toggle() {
assert_eq!(
parse_set_expr("number!"),
SetAction::Toggle {
name: "number".to_string()
}
);
}
#[test]
fn test_parse_reset() {
assert_eq!(
parse_set_expr("number&"),
SetAction::Reset {
name: "number".to_string()
}
);
}
#[test]
fn test_parse_assign() {
assert_eq!(
parse_set_expr("tabstop=8"),
SetAction::Assign {
name: "tabstop".to_string(),
raw_value: "8".to_string()
}
);
}
#[test]
fn test_parse_assign_string_value() {
assert_eq!(
parse_set_expr("theme=dark"),
SetAction::Assign {
name: "theme".to_string(),
raw_value: "dark".to_string()
}
);
}
#[test]
fn test_parse_assign_empty_value() {
assert_eq!(
parse_set_expr("opt="),
SetAction::Assign {
name: "opt".to_string(),
raw_value: String::new()
}
);
}
#[test]
fn test_parse_no_prefix() {
assert_eq!(
parse_set_expr("nonumber"),
SetAction::SetBool {
name: "number".to_string(),
value: false,
}
);
}
#[test]
fn test_parse_bare_name_bool_true() {
assert_eq!(
parse_set_expr("number"),
SetAction::SetBool {
name: "number".to_string(),
value: true,
}
);
}
#[test]
fn test_parse_no_alone_is_set_bool_false() {
assert_eq!(
parse_set_expr("no"),
SetAction::SetBool {
name: "no".to_string(),
value: true,
}
);
}
#[test]
fn test_parse_with_leading_whitespace() {
assert_eq!(
parse_set_expr(" number "),
SetAction::SetBool {
name: "number".to_string(),
value: true,
}
);
}
#[test]
fn test_parse_value_bool_true_variants() {
let expected = OptionValue::bool(false);
assert_eq!(parse_value_for_type("true", &expected, "opt").unwrap(), OptionValue::bool(true));
assert_eq!(parse_value_for_type("1", &expected, "opt").unwrap(), OptionValue::bool(true));
assert_eq!(parse_value_for_type("on", &expected, "opt").unwrap(), OptionValue::bool(true));
}
#[test]
fn test_parse_value_bool_false_variants() {
let expected = OptionValue::bool(true);
assert_eq!(
parse_value_for_type("false", &expected, "opt").unwrap(),
OptionValue::bool(false)
);
assert_eq!(parse_value_for_type("0", &expected, "opt").unwrap(), OptionValue::bool(false));
assert_eq!(parse_value_for_type("off", &expected, "opt").unwrap(), OptionValue::bool(false));
}
#[test]
fn test_parse_value_bool_invalid() {
let expected = OptionValue::bool(false);
let result = parse_value_for_type("maybe", &expected, "opt");
assert!(result.is_err());
assert!(result.unwrap_err().contains("expected bool"));
}
#[test]
fn test_parse_value_integer() {
let expected = OptionValue::int(0);
assert_eq!(parse_value_for_type("42", &expected, "opt").unwrap(), OptionValue::int(42));
}
#[test]
fn test_parse_value_negative_integer() {
let expected = OptionValue::int(0);
assert_eq!(parse_value_for_type("-5", &expected, "opt").unwrap(), OptionValue::int(-5));
}
#[test]
fn test_parse_value_integer_invalid() {
let expected = OptionValue::int(0);
let result = parse_value_for_type("abc", &expected, "opt");
assert!(result.is_err());
assert!(result.unwrap_err().contains("expected integer"));
}
#[test]
fn test_parse_value_string() {
let expected = OptionValue::string("default");
assert_eq!(
parse_value_for_type("hello", &expected, "opt").unwrap(),
OptionValue::string("hello")
);
}
#[test]
fn test_parse_value_choice() {
let choices = vec!["light".into(), "dark".into()];
let expected = OptionValue::choice("light", choices.clone());
assert_eq!(
parse_value_for_type("dark", &expected, "opt").unwrap(),
OptionValue::choice("dark", choices)
);
}
#[test]
fn test_set_command_id() {
let cmd = SetCommand;
assert_eq!(cmd.id().name(), "set");
assert_eq!(cmd.id().module().as_str(), "commands");
}
#[test]
fn test_set_command_names() {
let cmd = SetCommand;
let names = cmd.names();
assert_eq!(names.len(), 1);
assert!(names.contains(&"set"));
}
#[test]
fn test_set_command_description() {
let cmd = SetCommand;
let desc = cmd.description();
assert!(!desc.is_empty());
assert!(desc.contains("Set"));
}
#[test]
fn test_set_command_args() {
let cmd = SetCommand;
let args = cmd.args();
assert_eq!(args.len(), 1);
assert_eq!(args[0].name, "expr");
assert_eq!(args[0].kind, ArgKind::Rest);
assert!(!args[0].required);
}
#[test]
fn test_set_command_complete_returns_empty() {
let cmd = SetCommand;
let completions = cmd.complete("num");
assert!(completions.is_empty());
}
#[test]
fn test_set_command_debug() {
let cmd = SetCommand;
let debug = format!("{cmd:?}");
assert!(debug.contains("SetCommand"));
}
#[test]
fn test_set_command_is_send_sync() {
fn assert_send_sync<T: Send + Sync>() {}
assert_send_sync::<SetCommand>();
}
#[test]
fn test_set_command_clone_copy() {
let cmd = SetCommand;
let copy = cmd;
assert_eq!(cmd.id(), copy.id());
}
fn register_bool_option(harness: &reovim_driver_session::testing::TestSessionRuntime) {
harness
.kernel()
.options
.register(
reovim_kernel::api::v1::OptionSpec::new(
"number",
"Show line numbers",
OptionValue::bool(false),
)
.with_short("nu")
.with_scope(reovim_kernel::api::v1::OptionScope::Window),
)
.unwrap();
}
fn register_int_option(harness: &reovim_driver_session::testing::TestSessionRuntime) {
harness
.kernel()
.options
.register(reovim_kernel::api::v1::OptionSpec::new(
"tabstop",
"Number of spaces per tab",
OptionValue::int(4),
))
.unwrap();
}
fn register_string_option(harness: &reovim_driver_session::testing::TestSessionRuntime) {
harness
.kernel()
.options
.register(reovim_kernel::api::v1::OptionSpec::new(
"theme",
"Color theme",
OptionValue::string("default"),
))
.unwrap();
}
fn register_choice_option(harness: &reovim_driver_session::testing::TestSessionRuntime) {
harness
.kernel()
.options
.register(reovim_kernel::api::v1::OptionSpec::new(
"background",
"Background style",
OptionValue::choice("light", vec!["light".into(), "dark".into()]),
))
.unwrap();
}
fn register_constrained_int_option(harness: &reovim_driver_session::testing::TestSessionRuntime) {
harness
.kernel()
.options
.register(
reovim_kernel::api::v1::OptionSpec::new(
"scrolloff",
"Scroll offset",
OptionValue::int(0),
)
.with_constraint(reovim_kernel::api::v1::OptionConstraint::min(0)),
)
.unwrap();
}
fn make_ctx(expr: &str) -> CommandContext {
let mut ctx = CommandContext::new();
ctx.set("expr", reovim_driver_command_types::ArgValue::String(expr.to_string()));
ctx
}
#[test]
fn test_execute_set_bool_true() {
use reovim_driver_session::testing::TestSessionRuntime;
let mut harness = TestSessionRuntime::with_buffer("hello");
register_bool_option(&harness);
harness.with_runtime(|runtime| {
let cmd = SetCommand;
let ctx = make_ctx("number");
let result = cmd.execute(runtime, &ctx);
assert!(result.is_success());
let val = runtime
.kernel()
.options
.get("number", OptionScopeId::Global);
assert_eq!(val, Some(OptionValue::bool(true)));
});
}
#[test]
fn test_execute_set_bool_false() {
use reovim_driver_session::testing::TestSessionRuntime;
let mut harness = TestSessionRuntime::with_buffer("hello");
register_bool_option(&harness);
harness
.kernel()
.options
.set("number", OptionValue::bool(true), OptionScopeId::Global)
.unwrap();
harness.with_runtime(|runtime| {
let cmd = SetCommand;
let ctx = make_ctx("nonumber");
let result = cmd.execute(runtime, &ctx);
assert!(result.is_success());
let val = runtime
.kernel()
.options
.get("number", OptionScopeId::Global);
assert_eq!(val, Some(OptionValue::bool(false)));
});
}
#[test]
fn test_execute_toggle() {
use reovim_driver_session::testing::TestSessionRuntime;
let mut harness = TestSessionRuntime::with_buffer("hello");
register_bool_option(&harness);
harness.with_runtime(|runtime| {
let cmd = SetCommand;
let ctx = make_ctx("number!");
let result = cmd.execute(runtime, &ctx);
assert!(result.is_success());
let val = runtime
.kernel()
.options
.get("number", OptionScopeId::Global);
assert_eq!(val, Some(OptionValue::bool(true)));
});
}
#[test]
fn test_execute_assign_integer() {
use reovim_driver_session::testing::TestSessionRuntime;
let mut harness = TestSessionRuntime::with_buffer("hello");
register_int_option(&harness);
harness.with_runtime(|runtime| {
let cmd = SetCommand;
let ctx = make_ctx("tabstop=8");
let result = cmd.execute(runtime, &ctx);
assert!(result.is_success());
let val = runtime
.kernel()
.options
.get("tabstop", OptionScopeId::Global);
assert_eq!(val, Some(OptionValue::int(8)));
});
}
#[test]
fn test_execute_assign_string() {
use reovim_driver_session::testing::TestSessionRuntime;
let mut harness = TestSessionRuntime::with_buffer("hello");
register_string_option(&harness);
harness.with_runtime(|runtime| {
let cmd = SetCommand;
let ctx = make_ctx("theme=monokai");
let result = cmd.execute(runtime, &ctx);
assert!(result.is_success());
let val = runtime.kernel().options.get("theme", OptionScopeId::Global);
assert_eq!(val, Some(OptionValue::string("monokai")));
});
}
#[test]
fn test_execute_assign_choice() {
use reovim_driver_session::testing::TestSessionRuntime;
let mut harness = TestSessionRuntime::with_buffer("hello");
register_choice_option(&harness);
harness.with_runtime(|runtime| {
let cmd = SetCommand;
let ctx = make_ctx("background=dark");
let result = cmd.execute(runtime, &ctx);
assert!(result.is_success());
let val = runtime
.kernel()
.options
.get("background", OptionScopeId::Global);
assert_eq!(val, Some(OptionValue::choice("dark", vec!["light".into(), "dark".into()])));
});
}
#[test]
fn test_execute_assign_bool_via_equals() {
use reovim_driver_session::testing::TestSessionRuntime;
let mut harness = TestSessionRuntime::with_buffer("hello");
register_bool_option(&harness);
harness.with_runtime(|runtime| {
let cmd = SetCommand;
let ctx = make_ctx("number=true");
let result = cmd.execute(runtime, &ctx);
assert!(result.is_success());
let val = runtime
.kernel()
.options
.get("number", OptionScopeId::Global);
assert_eq!(val, Some(OptionValue::bool(true)));
});
}
#[test]
fn test_execute_reset() {
use reovim_driver_session::testing::TestSessionRuntime;
let mut harness = TestSessionRuntime::with_buffer("hello");
register_int_option(&harness);
harness
.kernel()
.options
.set("tabstop", OptionValue::int(8), OptionScopeId::Global)
.unwrap();
harness.with_runtime(|runtime| {
let cmd = SetCommand;
let ctx = make_ctx("tabstop&");
let result = cmd.execute(runtime, &ctx);
assert!(result.is_success());
let val = runtime
.kernel()
.options
.get("tabstop", OptionScopeId::Global);
assert_eq!(val, Some(OptionValue::int(4)));
});
}
#[test]
fn test_execute_reset_already_default() {
use reovim_driver_session::testing::TestSessionRuntime;
let mut harness = TestSessionRuntime::with_buffer("hello");
register_int_option(&harness);
harness.with_runtime(|runtime| {
let cmd = SetCommand;
let ctx = make_ctx("tabstop&");
let result = cmd.execute(runtime, &ctx);
assert!(result.is_success());
});
}
#[test]
fn test_execute_query() {
use reovim_driver_session::testing::TestSessionRuntime;
let mut harness = TestSessionRuntime::with_buffer("hello");
register_bool_option(&harness);
harness.with_runtime(|runtime| {
let cmd = SetCommand;
let ctx = make_ctx("number?");
let result = cmd.execute(runtime, &ctx);
assert!(result.is_success());
});
}
#[test]
fn test_execute_list_changed() {
use reovim_driver_session::testing::TestSessionRuntime;
let mut harness = TestSessionRuntime::with_buffer("hello");
register_bool_option(&harness);
harness.with_runtime(|runtime| {
let cmd = SetCommand;
let ctx = CommandContext::new(); let result = cmd.execute(runtime, &ctx);
assert!(result.is_success());
});
}
#[test]
fn test_execute_list_all() {
use reovim_driver_session::testing::TestSessionRuntime;
let mut harness = TestSessionRuntime::with_buffer("hello");
register_bool_option(&harness);
harness.with_runtime(|runtime| {
let cmd = SetCommand;
let ctx = make_ctx("all");
let result = cmd.execute(runtime, &ctx);
assert!(result.is_success());
});
}
#[test]
fn test_execute_short_alias() {
use reovim_driver_session::testing::TestSessionRuntime;
let mut harness = TestSessionRuntime::with_buffer("hello");
register_bool_option(&harness);
harness.with_runtime(|runtime| {
let cmd = SetCommand;
let ctx = make_ctx("nu"); let result = cmd.execute(runtime, &ctx);
assert!(result.is_success());
let val = runtime
.kernel()
.options
.get("number", OptionScopeId::Global);
assert_eq!(val, Some(OptionValue::bool(true)));
});
}
#[test]
fn test_execute_short_alias_query() {
use reovim_driver_session::testing::TestSessionRuntime;
let mut harness = TestSessionRuntime::with_buffer("hello");
register_bool_option(&harness);
harness.with_runtime(|runtime| {
let cmd = SetCommand;
let ctx = make_ctx("nu?");
let result = cmd.execute(runtime, &ctx);
assert!(result.is_success());
});
}
#[test]
fn test_execute_bare_name_non_bool_shows_value() {
use reovim_driver_session::testing::TestSessionRuntime;
let mut harness = TestSessionRuntime::with_buffer("hello");
register_int_option(&harness);
harness.with_runtime(|runtime| {
let cmd = SetCommand;
let ctx = make_ctx("tabstop"); let result = cmd.execute(runtime, &ctx);
assert!(result.is_success());
});
}
#[test]
fn test_execute_unknown_option() {
use reovim_driver_session::testing::TestSessionRuntime;
let mut harness = TestSessionRuntime::with_buffer("hello");
harness.with_runtime(|runtime| {
let cmd = SetCommand;
let ctx = make_ctx("nonexistent");
let result = cmd.execute(runtime, &ctx);
assert!(result.is_error());
});
}
#[test]
fn test_execute_unknown_option_query() {
use reovim_driver_session::testing::TestSessionRuntime;
let mut harness = TestSessionRuntime::with_buffer("hello");
harness.with_runtime(|runtime| {
let cmd = SetCommand;
let ctx = make_ctx("nonexistent?");
let result = cmd.execute(runtime, &ctx);
assert!(result.is_error());
});
}
#[test]
fn test_execute_unknown_option_toggle() {
use reovim_driver_session::testing::TestSessionRuntime;
let mut harness = TestSessionRuntime::with_buffer("hello");
harness.with_runtime(|runtime| {
let cmd = SetCommand;
let ctx = make_ctx("nonexistent!");
let result = cmd.execute(runtime, &ctx);
assert!(result.is_error());
});
}
#[test]
fn test_execute_unknown_option_assign() {
use reovim_driver_session::testing::TestSessionRuntime;
let mut harness = TestSessionRuntime::with_buffer("hello");
harness.with_runtime(|runtime| {
let cmd = SetCommand;
let ctx = make_ctx("nonexistent=5");
let result = cmd.execute(runtime, &ctx);
assert!(result.is_error());
});
}
#[test]
fn test_execute_unknown_option_reset() {
use reovim_driver_session::testing::TestSessionRuntime;
let mut harness = TestSessionRuntime::with_buffer("hello");
harness.with_runtime(|runtime| {
let cmd = SetCommand;
let ctx = make_ctx("nonexistent&");
let result = cmd.execute(runtime, &ctx);
assert!(result.is_error());
});
}
#[test]
fn test_execute_type_mismatch_toggle_on_int() {
use reovim_driver_session::testing::TestSessionRuntime;
let mut harness = TestSessionRuntime::with_buffer("hello");
register_int_option(&harness);
harness.with_runtime(|runtime| {
let cmd = SetCommand;
let ctx = make_ctx("tabstop!");
let result = cmd.execute(runtime, &ctx);
assert!(result.is_error());
});
}
#[test]
fn test_execute_type_mismatch_assign_string_to_int() {
use reovim_driver_session::testing::TestSessionRuntime;
let mut harness = TestSessionRuntime::with_buffer("hello");
register_int_option(&harness);
harness.with_runtime(|runtime| {
let cmd = SetCommand;
let ctx = make_ctx("tabstop=abc");
let result = cmd.execute(runtime, &ctx);
assert!(result.is_error());
});
}
#[test]
fn test_execute_type_mismatch_set_bool_on_int() {
use reovim_driver_session::testing::TestSessionRuntime;
let mut harness = TestSessionRuntime::with_buffer("hello");
register_int_option(&harness);
harness.with_runtime(|runtime| {
let cmd = SetCommand;
let ctx = make_ctx("notabstop");
let result = cmd.execute(runtime, &ctx);
assert!(result.is_error());
});
}
#[test]
fn test_execute_constraint_violation() {
use reovim_driver_session::testing::TestSessionRuntime;
let mut harness = TestSessionRuntime::with_buffer("hello");
register_constrained_int_option(&harness);
harness.with_runtime(|runtime| {
let cmd = SetCommand;
let ctx = make_ctx("scrolloff=-1");
let result = cmd.execute(runtime, &ctx);
assert!(result.is_error());
});
}
#[test]
fn test_event_emitted_on_set() {
use {
reovim_driver_session::testing::TestSessionRuntime,
std::sync::{
Arc, Mutex,
atomic::{AtomicBool, Ordering},
},
};
let mut harness = TestSessionRuntime::with_buffer("hello");
register_bool_option(&harness);
let event_received = Arc::new(AtomicBool::new(false));
let event_data = Arc::new(Mutex::new(None::<OptionChanged>));
let flag = Arc::clone(&event_received);
let data = Arc::clone(&event_data);
let _sub = harness
.kernel()
.event_bus
.subscribe::<OptionChanged, _>(0, move |event| {
flag.store(true, Ordering::SeqCst);
*data.lock().unwrap() = Some(event.clone());
reovim_kernel::api::v1::EventResult::Handled
});
harness.with_runtime(|runtime| {
let cmd = SetCommand;
let ctx = make_ctx("number");
let result = cmd.execute(runtime, &ctx);
assert!(result.is_success());
});
assert!(event_received.load(Ordering::SeqCst), "OptionChanged event should be emitted");
let event = event_data.lock().unwrap().clone().unwrap();
assert_eq!(event.name, "number");
assert_eq!(event.new_value, "true");
assert_eq!(event.source, ChangeSource::UserCommand);
assert_eq!(event.scope, OptionScopeId::Global);
}
#[test]
fn test_event_emitted_on_toggle() {
use {
reovim_driver_session::testing::TestSessionRuntime,
std::sync::{
Arc,
atomic::{AtomicBool, Ordering},
},
};
let mut harness = TestSessionRuntime::with_buffer("hello");
register_bool_option(&harness);
let event_received = Arc::new(AtomicBool::new(false));
let flag = Arc::clone(&event_received);
let _sub = harness
.kernel()
.event_bus
.subscribe::<OptionChanged, _>(0, move |_event| {
flag.store(true, Ordering::SeqCst);
reovim_kernel::api::v1::EventResult::Handled
});
harness.with_runtime(|runtime| {
let cmd = SetCommand;
let ctx = make_ctx("number!");
let result = cmd.execute(runtime, &ctx);
assert!(result.is_success());
});
assert!(
event_received.load(Ordering::SeqCst),
"OptionChanged event should be emitted on toggle"
);
}
#[test]
fn test_event_emitted_on_reset() {
use {
reovim_driver_session::testing::TestSessionRuntime,
std::sync::{
Arc,
atomic::{AtomicBool, Ordering},
},
};
let mut harness = TestSessionRuntime::with_buffer("hello");
register_int_option(&harness);
harness
.kernel()
.options
.set("tabstop", OptionValue::int(8), OptionScopeId::Global)
.unwrap();
let event_received = Arc::new(AtomicBool::new(false));
let flag = Arc::clone(&event_received);
let _sub = harness
.kernel()
.event_bus
.subscribe::<OptionReset, _>(0, move |_event| {
flag.store(true, Ordering::SeqCst);
reovim_kernel::api::v1::EventResult::Handled
});
harness.with_runtime(|runtime| {
let cmd = SetCommand;
let ctx = make_ctx("tabstop&");
let result = cmd.execute(runtime, &ctx);
assert!(result.is_success());
});
assert!(
event_received.load(Ordering::SeqCst),
"OptionReset event should be emitted on reset"
);
}
#[test]
fn test_no_event_on_error() {
use {
reovim_driver_session::testing::TestSessionRuntime,
std::sync::{
Arc,
atomic::{AtomicBool, Ordering},
},
};
let mut harness = TestSessionRuntime::with_buffer("hello");
let event_received = Arc::new(AtomicBool::new(false));
let flag = Arc::clone(&event_received);
let _sub = harness
.kernel()
.event_bus
.subscribe::<OptionChanged, _>(0, move |_event| {
flag.store(true, Ordering::SeqCst);
reovim_kernel::api::v1::EventResult::Handled
});
harness.with_runtime(|runtime| {
let cmd = SetCommand;
let ctx = make_ctx("nonexistent");
let result = cmd.execute(runtime, &ctx);
assert!(result.is_error());
});
assert!(!event_received.load(Ordering::SeqCst), "No event should be emitted on error");
}
#[test]
fn test_state_changes_recorded_on_set() {
use reovim_driver_session::{ChangeTracker, testing::TestSessionRuntime};
let mut harness = TestSessionRuntime::with_buffer("hello");
register_bool_option(&harness);
harness.with_runtime(|runtime| {
let cmd = SetCommand;
let ctx = make_ctx("number");
let result = cmd.execute(runtime, &ctx);
assert!(result.is_success());
let changes = runtime.take_changes();
assert!(changes.option_changed);
assert_eq!(changes.options_changed.len(), 1);
assert_eq!(changes.options_changed[0].name, "number");
assert_eq!(changes.options_changed[0].value, OptionValue::bool(true));
});
}
#[test]
fn test_state_changes_recorded_on_toggle() {
use reovim_driver_session::{ChangeTracker, testing::TestSessionRuntime};
let mut harness = TestSessionRuntime::with_buffer("hello");
register_bool_option(&harness);
harness.with_runtime(|runtime| {
let cmd = SetCommand;
let ctx = make_ctx("number!");
let result = cmd.execute(runtime, &ctx);
assert!(result.is_success());
let changes = runtime.take_changes();
assert!(changes.option_changed);
assert_eq!(changes.options_changed.len(), 1);
assert_eq!(changes.options_changed[0].name, "number");
});
}
#[test]
fn test_state_changes_recorded_on_reset() {
use reovim_driver_session::{ChangeTracker, testing::TestSessionRuntime};
let mut harness = TestSessionRuntime::with_buffer("hello");
register_int_option(&harness);
harness
.kernel()
.options
.set("tabstop", OptionValue::int(8), OptionScopeId::Global)
.unwrap();
harness.with_runtime(|runtime| {
let cmd = SetCommand;
let ctx = make_ctx("tabstop&");
let result = cmd.execute(runtime, &ctx);
assert!(result.is_success());
let changes = runtime.take_changes();
assert!(changes.option_changed);
assert_eq!(changes.options_changed.len(), 1);
assert_eq!(changes.options_changed[0].name, "tabstop");
assert_eq!(changes.options_changed[0].value, OptionValue::int(4));
});
}
#[test]
fn test_old_value_uses_default_when_none() {
use {
reovim_driver_session::testing::TestSessionRuntime,
std::sync::{Arc, Mutex},
};
let mut harness = TestSessionRuntime::with_buffer("hello");
register_bool_option(&harness);
let event_data = Arc::new(Mutex::new(None::<OptionChanged>));
let data = Arc::clone(&event_data);
let _sub = harness
.kernel()
.event_bus
.subscribe::<OptionChanged, _>(0, move |event| {
*data.lock().unwrap() = Some(event.clone());
reovim_kernel::api::v1::EventResult::Handled
});
harness.with_runtime(|runtime| {
let cmd = SetCommand;
let ctx = make_ctx("number");
let result = cmd.execute(runtime, &ctx);
assert!(result.is_success());
});
let event = event_data.lock().unwrap().clone().unwrap();
assert_eq!(event.old_value, "false"); assert_eq!(event.new_value, "true");
}
#[test]
fn test_old_value_uses_previous_when_some() {
use {
reovim_driver_session::testing::TestSessionRuntime,
std::sync::{Arc, Mutex},
};
let mut harness = TestSessionRuntime::with_buffer("hello");
register_int_option(&harness);
harness
.kernel()
.options
.set("tabstop", OptionValue::int(8), OptionScopeId::Global)
.unwrap();
let event_data = Arc::new(Mutex::new(None::<OptionChanged>));
let data = Arc::clone(&event_data);
let _sub = harness
.kernel()
.event_bus
.subscribe::<OptionChanged, _>(0, move |event| {
*data.lock().unwrap() = Some(event.clone());
reovim_kernel::api::v1::EventResult::Handled
});
harness.with_runtime(|runtime| {
let cmd = SetCommand;
let ctx = make_ctx("tabstop=2");
let result = cmd.execute(runtime, &ctx);
assert!(result.is_success());
});
let event = event_data.lock().unwrap().clone().unwrap();
assert_eq!(event.old_value, "8"); assert_eq!(event.new_value, "2");
}
#[test]
fn test_execute_list_all_empty() {
use reovim_driver_session::testing::TestSessionRuntime;
let mut harness = TestSessionRuntime::with_buffer("hello");
harness.with_runtime(|runtime| {
let cmd = SetCommand;
let ctx = make_ctx("all");
let result = cmd.execute(runtime, &ctx);
assert!(result.is_success());
});
}
#[test]
fn test_execute_list_changed_empty() {
use reovim_driver_session::testing::TestSessionRuntime;
let mut harness = TestSessionRuntime::with_buffer("hello");
harness.with_runtime(|runtime| {
let cmd = SetCommand;
let ctx = CommandContext::new();
let result = cmd.execute(runtime, &ctx);
assert!(result.is_success());
});
}
#[test]
fn test_execute_list_changed_with_changes() {
use reovim_driver_session::testing::TestSessionRuntime;
let mut harness = TestSessionRuntime::with_buffer("hello");
register_bool_option(&harness);
harness
.kernel()
.options
.set("number", OptionValue::bool(true), OptionScopeId::Global)
.unwrap();
harness.with_runtime(|runtime| {
let cmd = SetCommand;
let ctx = CommandContext::new();
let result = cmd.execute(runtime, &ctx);
assert!(result.is_success());
});
}
#[test]
fn test_execute_assign_bool_invalid() {
use reovim_driver_session::testing::TestSessionRuntime;
let mut harness = TestSessionRuntime::with_buffer("hello");
register_bool_option(&harness);
harness.with_runtime(|runtime| {
let cmd = SetCommand;
let ctx = make_ctx("number=maybe");
let result = cmd.execute(runtime, &ctx);
assert!(result.is_error());
});
}
#[test]
fn test_event_emitted_on_assign() {
use {
reovim_driver_session::testing::TestSessionRuntime,
std::sync::{
Arc,
atomic::{AtomicBool, Ordering},
},
};
let mut harness = TestSessionRuntime::with_buffer("hello");
register_int_option(&harness);
let event_received = Arc::new(AtomicBool::new(false));
let flag = Arc::clone(&event_received);
let _sub = harness
.kernel()
.event_bus
.subscribe::<OptionChanged, _>(0, move |_event| {
flag.store(true, Ordering::SeqCst);
reovim_kernel::api::v1::EventResult::Handled
});
harness.with_runtime(|runtime| {
let cmd = SetCommand;
let ctx = make_ctx("tabstop=8");
let result = cmd.execute(runtime, &ctx);
assert!(result.is_success());
});
assert!(
event_received.load(Ordering::SeqCst),
"OptionChanged event should be emitted on assign"
);
}
#[test]
fn test_state_changes_recorded_on_assign() {
use reovim_driver_session::{ChangeTracker, testing::TestSessionRuntime};
let mut harness = TestSessionRuntime::with_buffer("hello");
register_int_option(&harness);
harness.with_runtime(|runtime| {
let cmd = SetCommand;
let ctx = make_ctx("tabstop=8");
let result = cmd.execute(runtime, &ctx);
assert!(result.is_success());
let changes = runtime.take_changes();
assert!(changes.option_changed);
assert_eq!(changes.options_changed[0].name, "tabstop");
assert_eq!(changes.options_changed[0].value, OptionValue::int(8));
});
}
#[test]
fn test_set_action_debug() {
let action = SetAction::ListChanged;
let debug = format!("{action:?}");
assert!(debug.contains("ListChanged"));
}
#[test]
fn test_set_action_clone() {
let action = SetAction::Show {
name: "number".to_string(),
};
let cloned = action.clone();
assert_eq!(action, cloned);
}