use textual::screen::{Screen, ScreenStack};
use textual::widgets::{CommandPaletteScreen, PaletteCommand, SystemModalScreen};
use rich_rs::{Console, ConsoleOptions, Segments};
struct StubWidget;
impl textual::widgets::Widget for StubWidget {
fn render(&self, _console: &Console, _options: &ConsoleOptions) -> Segments {
Segments::new()
}
fn style_type(&self) -> &'static str {
"StubWidget"
}
}
struct NamedScreen {
name: String,
}
impl NamedScreen {
fn new(name: &str) -> Self {
Self {
name: name.to_string(),
}
}
fn boxed(name: &str) -> Box<dyn Screen> {
Box::new(Self::new(name))
}
}
impl Screen for NamedScreen {
fn name(&self) -> &str {
&self.name
}
fn compose(&self) -> Box<dyn textual::widgets::Widget> {
Box::new(StubWidget)
}
}
#[test]
fn mode_factory_creates_screen() {
let factory: Box<dyn Fn() -> Box<dyn Screen>> = Box::new(|| NamedScreen::boxed("HelpMode"));
let screen = factory();
assert_eq!(screen.name(), "HelpMode");
let screen2 = factory();
assert_eq!(screen2.name(), "HelpMode");
}
#[test]
fn mode_registry_map() {
use std::collections::HashMap;
let mut modes: HashMap<String, Box<dyn Fn() -> Box<dyn Screen>>> = HashMap::new();
modes.insert(
"help".to_string(),
Box::new(|| NamedScreen::boxed("HelpScreen")),
);
modes.insert(
"settings".to_string(),
Box::new(|| NamedScreen::boxed("SettingsScreen")),
);
let help_screen = modes["help"]();
assert_eq!(help_screen.name(), "HelpScreen");
let settings_screen = modes["settings"]();
assert_eq!(settings_screen.name(), "SettingsScreen");
}
#[test]
fn mode_switch_pops_old_and_pushes_new() {
let mut stack = ScreenStack::new();
let help_screen = NamedScreen::boxed("HelpScreen");
stack.push(help_screen);
assert_eq!(stack.len(), 1);
let (popped, _, _) = stack.pop().unwrap();
assert_eq!(popped.name(), "HelpScreen");
let settings_screen = NamedScreen::boxed("SettingsScreen");
stack.push(settings_screen);
assert_eq!(stack.len(), 1);
let (popped, _, _) = stack.pop().unwrap();
assert_eq!(popped.name(), "SettingsScreen");
}
#[test]
fn mode_switch_preserves_base_screens() {
let mut stack = ScreenStack::new();
stack.push(NamedScreen::boxed("BaseScreen"));
assert_eq!(stack.len(), 1);
stack.push(NamedScreen::boxed("ModeA"));
assert_eq!(stack.len(), 2);
let (popped, _, _) = stack.pop().unwrap();
assert_eq!(popped.name(), "ModeA");
stack.push(NamedScreen::boxed("ModeB"));
assert_eq!(stack.len(), 2);
let (popped, _, _) = stack.pop().unwrap();
assert_eq!(popped.name(), "ModeB");
assert_eq!(stack.len(), 1);
let (popped, _, _) = stack.pop().unwrap();
assert_eq!(popped.name(), "BaseScreen");
}
#[test]
fn same_mode_noop() {
let mut current_mode: Option<String> = None;
let mut stack = ScreenStack::new();
let mode_name = "help";
assert_ne!(current_mode.as_deref(), Some(mode_name));
let screen = NamedScreen::boxed("HelpScreen");
stack.push(screen);
current_mode = Some(mode_name.to_string());
assert_eq!(stack.len(), 1);
assert_eq!(current_mode.as_deref(), Some(mode_name));
assert_eq!(stack.len(), 1);
}
#[test]
fn command_palette_screen_name() {
let screen = CommandPaletteScreen::new();
assert_eq!(screen.name(), "CommandPaletteScreen");
}
#[test]
fn command_palette_screen_is_modal() {
let screen = CommandPaletteScreen::new();
assert!(screen.is_modal());
}
#[test]
fn command_palette_screen_composes_widget() {
let screen = CommandPaletteScreen::new();
let widget = screen.compose();
assert_eq!(widget.style_type(), "CommandPalette");
}
#[test]
fn command_palette_screen_with_commands() {
let commands = vec![
PaletteCommand::new("test", "Test Command", "Run tests"),
PaletteCommand::new("deploy", "Deploy", "Deploy to production"),
];
let screen = CommandPaletteScreen::with_commands(commands);
assert_eq!(screen.name(), "CommandPaletteScreen");
let widget = screen.compose();
assert_eq!(widget.style_type(), "CommandPalette");
}
#[test]
fn command_palette_screen_default() {
let screen = CommandPaletteScreen::default();
assert_eq!(screen.name(), "CommandPaletteScreen");
}
#[test]
fn system_modal_screen_no_inherit_css() {
let screen = CommandPaletteScreen::new();
assert!(!screen.inherit_css());
}
#[test]
fn command_palette_screen_on_stack() {
let mut stack = ScreenStack::new();
stack.push(Box::new(CommandPaletteScreen::new()));
assert_eq!(stack.len(), 1);
let (popped, _, _) = stack.pop().unwrap();
assert_eq!(popped.name(), "CommandPaletteScreen");
}
#[test]
fn command_palette_screen_push_pop() {
let mut stack = ScreenStack::new();
stack.push(NamedScreen::boxed("Base"));
stack.push(Box::new(CommandPaletteScreen::new()));
assert_eq!(stack.len(), 2);
let (screen, _result, _) = stack.pop().unwrap();
assert_eq!(screen.name(), "CommandPaletteScreen");
assert_eq!(stack.len(), 1);
let (base, _, _) = stack.pop().unwrap();
assert_eq!(base.name(), "Base");
}
#[test]
fn command_palette_as_mode_factory() {
use std::collections::HashMap;
let mut modes: HashMap<String, Box<dyn Fn() -> Box<dyn Screen>>> = HashMap::new();
modes.insert(
"command_palette".to_string(),
Box::new(|| Box::new(CommandPaletteScreen::new())),
);
let screen = modes["command_palette"]();
assert_eq!(screen.name(), "CommandPaletteScreen");
assert!(screen.is_modal());
}