dynamic_cli/plugin/builtin/
version.rs1use crate::config::schema::CommandsConfig;
11use crate::executor::CommandHandler;
12use crate::plugin::system::SystemVersionHandler;
13use crate::plugin::Plugin;
14
15pub struct VersionPlugin {
46 config: Option<CommandsConfig>,
48}
49
50impl VersionPlugin {
51 pub fn new() -> Self {
62 Self { config: None }
63 }
64
65 pub fn with_config(mut self, config: CommandsConfig) -> Self {
92 self.config = Some(config);
93 self
94 }
95}
96
97impl Default for VersionPlugin {
98 fn default() -> Self {
99 Self::new()
100 }
101}
102
103impl Plugin for VersionPlugin {
104 fn name(&self) -> &str {
105 "version"
106 }
107
108 fn version(&self) -> &str {
109 env!("CARGO_PKG_VERSION")
110 }
111
112 fn description(&self) -> &str {
113 "Standalone version command (split out of SystemPlugin, #44)"
114 }
115
116 fn handlers(&self) -> Vec<(String, Box<dyn CommandHandler>)> {
117 vec![(
118 "system_version".to_string(),
119 Box::new(SystemVersionHandler::new(self.config.clone())),
120 )]
121 }
122}
123
124#[cfg(test)]
129mod tests {
130 use super::*;
131 use crate::config::schema::{CommandsConfig, Metadata};
132 use crate::context::ExecutionContext;
133 use crate::parser::ParsedArgs;
134 use std::any::Any;
135 use std::collections::HashMap;
136
137 #[derive(Default)]
138 struct TestContext;
139
140 impl ExecutionContext for TestContext {
141 fn as_any(&self) -> &dyn Any {
142 self
143 }
144 fn as_any_mut(&mut self) -> &mut dyn Any {
145 self
146 }
147 }
148
149 fn test_config() -> CommandsConfig {
150 CommandsConfig {
151 metadata: Metadata {
152 version: "2.0.0".to_string(),
153 prompt: "testapp".to_string(),
154 prompt_suffix: " > ".to_string(),
155 },
156 commands: vec![],
157 global_options: vec![],
158 directives: vec![],
159 }
160 }
161
162 #[test]
163 fn test_version_plugin_metadata() {
164 let p = VersionPlugin::new();
165 assert_eq!(p.name(), "version");
166 assert!(!p.version().is_empty());
167 assert!(!p.description().is_empty());
168 }
169
170 #[test]
171 fn test_version_plugin_default() {
172 let p = VersionPlugin::default();
173 assert_eq!(p.name(), "version");
174 }
175
176 #[test]
177 fn test_version_plugin_handler_name() {
178 let handlers = VersionPlugin::new().handlers();
179 assert_eq!(handlers.len(), 1);
180 assert_eq!(handlers[0].0, "system_version");
181 }
182
183 #[test]
184 fn test_version_plugin_with_config() {
185 let plugin = VersionPlugin::new().with_config(test_config());
186 assert!(plugin.config.is_some());
187 assert_eq!(plugin.config.unwrap().metadata.version, "2.0.0");
188 }
189
190 #[test]
191 fn test_version_handler_executes_with_config() {
192 let plugin = VersionPlugin::new().with_config(test_config());
193 let handlers = plugin.handlers();
194 let (_, handler) = &handlers[0];
195 let mut ctx = TestContext;
196 assert!(handler
197 .execute(&mut ctx, &ParsedArgs::from_scalars(HashMap::new()))
198 .is_ok());
199 }
200
201 #[test]
202 fn test_version_handler_executes_without_config() {
203 let handlers = VersionPlugin::new().handlers();
204 let (_, handler) = &handlers[0];
205 let mut ctx = TestContext;
206 assert!(handler
207 .execute(&mut ctx, &ParsedArgs::from_scalars(HashMap::new()))
208 .is_ok());
209 }
210
211 #[test]
212 fn test_version_plugin_is_send_sync() {
213 fn assert_send_sync<T: Send + Sync>(_: T) {}
214 assert_send_sync(VersionPlugin::new());
215 }
216}