use {
super::*,
reovim_driver_session::SessionRuntime,
reovim_kernel::api::v1::{CommandId, ModuleId},
};
struct TestCommand;
impl Command for TestCommand {
fn id(&self) -> CommandId {
CommandId::new(ModuleId::new("test"), "test-cmd")
}
fn description(&self) -> &'static str {
"A test command"
}
fn args(&self) -> Vec<ArgSpec> {
vec![ArgSpec::optional("count", ArgKind::Count, "Test count")]
}
fn names(&self) -> &[&'static str] {
&["test", "t"]
}
}
impl CommandHandler for TestCommand {
#[cfg_attr(coverage_nightly, coverage(off))]
fn execute(&self, _runtime: &mut SessionRuntime<'_>, _args: &CommandContext) -> CommandResult {
CommandResult::Success
}
}
#[test]
fn test_command_implementation() {
let cmd = TestCommand;
assert_eq!(cmd.id().name(), "test-cmd");
assert_eq!(cmd.description(), "A test command");
assert_eq!(cmd.args().len(), 1);
assert_eq!(cmd.names(), &["test", "t"]);
}
#[test]
fn test_command_handler_as_trait_object() {
let cmd: &dyn CommandHandler = &TestCommand;
assert_eq!(cmd.description(), "A test command");
}
#[test]
fn test_reexported_arg_kind_variants() {
let _ = ArgKind::Count;
let _ = ArgKind::Register;
let _ = ArgKind::Motion;
let _ = ArgKind::Range;
let _ = ArgKind::FilePath;
let _ = ArgKind::String;
let _ = ArgKind::Bang;
let _ = ArgKind::BufferId;
let _ = ArgKind::Char;
let _ = ArgKind::Rest;
}
#[test]
fn test_reexported_arg_value_variants() {
let _ = ArgValue::Count(1);
let _ = ArgValue::Register('a');
let _ = ArgValue::Motion("w".to_string());
let _ = ArgValue::Range(1, 5);
let _ = ArgValue::FilePath("f.txt".to_string());
let _ = ArgValue::String("s".to_string());
let _ = ArgValue::Bang(true);
let _ = ArgValue::BufferId(0);
let _ = ArgValue::Char('x');
let _ = ArgValue::Position(0, 0);
let _ = ArgValue::WindowId(0);
}
#[test]
fn test_reexported_command_result_variants() {
assert!(CommandResult::Success.is_success());
assert!(CommandResult::Error("e".to_string()).is_error());
}
#[test]
fn test_reexported_motion_type() {
let mt = MotionType::default();
assert!(mt.is_characterwise());
assert!(MotionType::Linewise.is_linewise());
}
#[test]
fn test_reexported_command_context() {
let mut ctx = CommandContext::new();
ctx.set("count", ArgValue::Count(3));
assert_eq!(ctx.count(), Some(3));
}
#[test]
fn test_reexported_arg_spec() {
let spec = ArgSpec::required("count", ArgKind::Count, "Number");
assert!(spec.required);
let spec = ArgSpec::optional("reg", ArgKind::Register, "Register");
assert!(!spec.required);
}
struct MinimalCommand;
impl Command for MinimalCommand {
fn id(&self) -> CommandId {
CommandId::new(ModuleId::new("test"), "minimal")
}
fn description(&self) -> &'static str {
"Minimal"
}
}
#[test]
fn test_minimal_command_defaults() {
let cmd = MinimalCommand;
assert!(cmd.args().is_empty());
assert!(cmd.names().is_empty());
}
#[test]
fn test_handler_store_integration() {
let store = CommandHandlerStore::new();
store.add(Box::new(TestCommand));
let handlers = store.take_handlers();
assert_eq!(handlers.len(), 1);
assert_eq!(handlers[0].id().name(), "test-cmd");
assert_eq!(handlers[0].names(), &["test", "t"]);
}
#[test]
fn test_reexported_parse_cmdline() {
let parsed = parse_cmdline("w! file.txt").unwrap();
assert_eq!(parsed.name, "w");
assert!(parsed.bang);
assert_eq!(parsed.args, vec!["file.txt"]);
assert!(parse_cmdline("").is_none());
}
#[test]
fn test_reexported_command_name_index() {
let mut idx = CommandNameIndex::new();
let cmd: std::sync::Arc<dyn Command> = std::sync::Arc::new(TestCommand);
let id = cmd.id();
for &name in cmd.names() {
idx.insert(name.to_string(), id.clone(), std::sync::Arc::clone(&cmd));
}
assert_eq!(idx.count(), 1);
assert!(idx.resolve("test").is_some());
assert!(idx.resolve("t").is_some());
}
#[test]
fn test_reexported_resolve_prefix() {
let mut idx = CommandNameIndex::new();
let cmd: std::sync::Arc<dyn Command> = std::sync::Arc::new(TestCommand);
let id = cmd.id();
for &name in cmd.names() {
idx.insert(name.to_string(), id.clone(), std::sync::Arc::clone(&cmd));
}
let result = idx.resolve_prefix("tes").unwrap().unwrap();
assert_eq!(result.0.name(), "test-cmd");
}
#[test]
fn test_reexported_ambiguous_prefix() {
let _ = AmbiguousPrefix {
prefix: "s".to_string(),
candidates: vec!["set".to_string()],
};
}
#[test]
fn test_command_info_from_test_command() {
let cmd = TestCommand;
let info = CommandInfo::from_command(&cmd);
assert_eq!(info.id.name(), "test-cmd");
assert_eq!(info.names, vec!["test", "t"]);
assert_eq!(info.description, "A test command");
assert_eq!(info.args.len(), 1);
assert!(info.has_user_names());
}
#[test]
fn test_command_info_from_minimal_command() {
let cmd = MinimalCommand;
let info = CommandInfo::from_command(&cmd);
assert_eq!(info.id.name(), "minimal");
assert!(info.names.is_empty());
assert_eq!(info.description, "Minimal");
assert!(info.args.is_empty());
assert!(!info.has_user_names());
}