use std::sync::Arc;
use crate::SqlModelConsole;
pub trait ConsoleAware {
fn set_console(&mut self, console: Option<Arc<SqlModelConsole>>);
fn console(&self) -> Option<&Arc<SqlModelConsole>>;
fn has_console(&self) -> bool {
self.console().is_some()
}
fn emit_status(&self, message: &str) {
if let Some(console) = self.console() {
console.status(message);
}
}
fn emit_success(&self, message: &str) {
if let Some(console) = self.console() {
console.success(message);
}
}
fn emit_error(&self, message: &str) {
if let Some(console) = self.console() {
console.error(message);
}
}
fn emit_warning(&self, message: &str) {
if let Some(console) = self.console() {
console.warning(message);
}
}
fn emit_info(&self, message: &str) {
if let Some(console) = self.console() {
console.info(message);
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::OutputMode;
struct MockConnection {
console: Option<Arc<SqlModelConsole>>,
}
impl MockConnection {
fn new() -> Self {
Self { console: None }
}
}
impl ConsoleAware for MockConnection {
fn set_console(&mut self, console: Option<Arc<SqlModelConsole>>) {
self.console = console;
}
fn console(&self) -> Option<&Arc<SqlModelConsole>> {
self.console.as_ref()
}
}
#[test]
fn test_has_console_false_initially() {
let conn = MockConnection::new();
assert!(!conn.has_console());
}
#[test]
fn test_has_console_true_after_set() {
let mut conn = MockConnection::new();
let console = Arc::new(SqlModelConsole::with_mode(OutputMode::Plain));
conn.set_console(Some(console));
assert!(conn.has_console());
}
#[test]
fn test_set_console_none_detaches() {
let mut conn = MockConnection::new();
let console = Arc::new(SqlModelConsole::with_mode(OutputMode::Plain));
conn.set_console(Some(console));
assert!(conn.has_console());
conn.set_console(None);
assert!(!conn.has_console());
}
#[test]
fn test_console_returns_reference() {
let mut conn = MockConnection::new();
let console = Arc::new(SqlModelConsole::with_mode(OutputMode::Plain));
conn.set_console(Some(console.clone()));
let returned = conn.console().unwrap();
assert!(returned.is_plain());
}
#[test]
fn test_emit_methods_no_panic_without_console() {
let conn = MockConnection::new();
conn.emit_status("test status");
conn.emit_success("test success");
conn.emit_error("test error");
conn.emit_warning("test warning");
conn.emit_info("test info");
}
#[test]
fn test_emit_methods_with_console() {
let mut conn = MockConnection::new();
let console = Arc::new(SqlModelConsole::with_mode(OutputMode::Plain));
conn.set_console(Some(console));
conn.emit_status("connecting to database");
conn.emit_success("connection established");
conn.emit_error("query failed");
conn.emit_warning("deprecated feature used");
conn.emit_info("using connection pool");
}
#[test]
fn test_shared_console_across_components() {
let console = Arc::new(SqlModelConsole::with_mode(OutputMode::Json));
let mut conn1 = MockConnection::new();
let mut conn2 = MockConnection::new();
conn1.set_console(Some(console.clone()));
conn2.set_console(Some(console.clone()));
assert!(conn1.console().unwrap().is_json());
assert!(conn2.console().unwrap().is_json());
assert_eq!(Arc::strong_count(&console), 3);
}
#[test]
fn test_console_none_returns_none() {
let conn = MockConnection::new();
assert!(conn.console().is_none());
}
}