Lines
100 %
Functions
Branches
//! Unit tests for the view module.
use super::*;
use crate::pane::PaneId;
use crate::tabs::config::ConfigTab;
use crate::tabs::list::ListTab;
use crate::tabs::nms::ConsoleState;
use crate::tabs::reports::ReportsTab;
use crate::widgets::EditMode;
use cli_core::render::schema;
fn make_ctx() -> DrawCtx {
DrawCtx {
edit_mode: EditMode::Emacs,
is_active: false,
}
#[test]
fn view_id_all_has_six_entries() {
assert_eq!(ViewId::ALL.len(), 6);
fn view_id_index_matches_discriminant() {
assert_eq!(ViewId::Accounts.index(), 0);
assert_eq!(ViewId::Transactions.index(), 1);
assert_eq!(ViewId::Commodities.index(), 2);
assert_eq!(ViewId::Reports.index(), 3);
assert_eq!(ViewId::Config.index(), 4);
assert_eq!(ViewId::Console.index(), 5);
fn view_id_all_round_trips_through_index() {
for (i, id) in ViewId::ALL.iter().enumerate() {
assert_eq!(id.index(), i);
fn view_id_labels_are_non_empty() {
for id in ViewId::ALL {
assert!(!id.label().is_empty());
fn tab_alias_matches_view_id() {
assert_eq!(Tab::Accounts, ViewId::Accounts);
assert_eq!(Tab::Console, ViewId::Console);
fn view_ref_list_id_and_title() {
let tab = ListTab::new("(list-accounts)", &schema::ACCOUNTS);
let vr = ViewRef::List(ViewId::Accounts, &tab);
assert_eq!(vr.id(), ViewId::Accounts);
assert_eq!(vr.title(), "Accounts");
fn view_ref_reports_id_and_title() {
let tab = ReportsTab::new();
let vr = ViewRef::Reports(&tab);
assert_eq!(vr.id(), ViewId::Reports);
assert_eq!(vr.title(), "Reports");
fn view_ref_config_id_and_title() {
let tab = ConfigTab::new();
let vr = ViewRef::Config(&tab);
assert_eq!(vr.id(), ViewId::Config);
assert_eq!(vr.title(), "Config");
fn view_ref_console_id_and_title() {
let tab = ConsoleState::new();
let vr = ViewRef::Console(&tab);
assert_eq!(vr.id(), ViewId::Console);
assert_eq!(vr.title(), "Console");
fn list_handle_select_next_consumed() {
let mut tab = ListTab::new("(list-accounts)", &schema::ACCOUNTS);
let ctx = make_ctx();
assert!(matches!(
tab.handle(crate::event::Intent::ListSelectNext, &ctx),
Handled::Consumed(_)
));
fn list_handle_unknown_intent_ignored() {
tab.handle(crate::event::Intent::Quit, &ctx),
Handled::Ignored
fn reports_handle_always_ignored() {
let mut tab = ReportsTab::new();
fn console_handle_always_ignored() {
let mut tab = ConsoleState::new();
fn view_mut_list_handle_consumed() {
let mut vm = ViewMut::List(ViewId::Accounts, &mut tab);
vm.handle(crate::event::Intent::ListSelectNext, &ctx),
fn view_mut_config_handle_select_consumed() {
let mut tab = ConfigTab::new();
let mut vm = ViewMut::Config(&mut tab);
fn draw_console_scroll_zero_shows_newest_line() {
use ratatui::Terminal;
use ratatui::backend::TestBackend;
use ratatui::layout::Rect;
let mut state = ConsoleState::new();
for i in 0..20 {
state.push_scrollback(format!("line{i:02}"));
let ctx = DrawCtx {
};
let backend = TestBackend::new(40, 12);
let mut terminal = Terminal::new(backend).expect("terminal");
terminal
.draw(|f| {
let area = Rect::new(0, 0, 40, 12);
state.draw(f, area, &ctx);
})
.expect("draw");
let buf = terminal.backend().buffer().clone();
let rendered: String = (0..buf.area.height)
.map(|y| {
(0..buf.area.width)
.map(|x| {
buf.cell((x, y))
.map_or(' ', |c| c.symbol().chars().next().unwrap_or(' '))
.collect::<String>()
.collect::<Vec<_>>()
.join("\n");
assert!(
rendered.contains("line19"),
"newest line missing:\n{rendered}"
);
!rendered.contains("line00"),
"oldest line should be scrolled off:\n{rendered}"
fn draw_console_scroll_up_shows_older_lines() {
state.scroll_up(10);
!rendered.contains("line19"),
"newest line should be scrolled off:\n{rendered}"
fn draw_console_scrollback_pane_focused_changes_title() {
state.panes.focus(PaneId::Scrollback);
is_active: true,
let first_row: String = (0..buf.area.width)
buf.cell((x, 0))
.collect();
first_row.contains('S'),
"Scrollback title missing: {first_row}"