use crossterm::event::{KeyCode, KeyEvent, KeyModifiers};
use ratada::Screen;
use ratatui::Terminal;
use ratatui::backend::TestBackend;
use crate::config::Config;
use crate::domain::evaluator::MevalEvaluator;
use crate::domain::history::History;
use crate::domain::quantity::Quantity;
use crate::domain::variables::VariableStore;
use crate::services::CalcService;
use crate::storage::UiState;
use crate::tui::app::App;
use crate::tui::interaction::Headless;
pub(super) fn key(code: KeyCode) -> KeyEvent {
KeyEvent::new(code, KeyModifiers::NONE)
}
pub(super) fn chord(code: KeyCode, modifiers: KeyModifiers) -> KeyEvent {
KeyEvent::new(code, modifiers)
}
pub(super) fn test_app() -> App {
app_with(&Config::default())
}
pub(super) fn app_with(config: &Config) -> App {
app_with_state(config, &UiState::default())
}
pub(super) fn app_with_state(config: &Config, ui: &UiState) -> App {
let service = CalcService::new(
Box::new(MevalEvaluator::new()),
config.format_settings(),
History::new(100),
VariableStore::new(),
);
App::new(service, config, ui)
}
pub(super) fn press(app: &mut App, key: KeyEvent) {
app.dispatch(key, &mut Headless::accepting())
.expect("dispatch must not fail headlessly");
}
pub(super) fn type_text(app: &mut App, text: &str) {
for character in text.chars() {
press(app, key(KeyCode::Char(character)));
}
}
pub(super) fn submit(app: &mut App, text: &str) {
type_text(app, text);
press(app, key(KeyCode::Enter));
}
pub(super) fn value_at(app: &App, index: usize) -> Option<f64> {
app.service().history().entries()[index]
.value
.as_ref()
.map(Quantity::display_value)
}
pub(super) fn render_to_string(app: &App, width: u16, height: u16) -> String {
let backend = TestBackend::new(width, height);
let mut terminal = Terminal::new(backend).expect("test terminal");
terminal.draw(|frame| app.render(frame)).expect("draw");
terminal
.backend()
.buffer()
.content()
.iter()
.map(|cell| cell.symbol())
.collect()
}