revw 0.2.3

A vim-like TUI for managing notes and resources
Documentation
use revw::app::{App, FormatMode};

#[test]
fn test_overlay_scroll_initialization() {
    let app = App::new(FormatMode::View);
    assert_eq!(app.edit_hscroll, 0);
    assert_eq!(app.edit_vscroll, 0);
}

#[test]
fn test_cancel_editing_resets_scroll() {
    let mut app = App::new(FormatMode::View);
    app.editing_entry = true;
    app.edit_hscroll = 10;
    app.edit_vscroll = 5;

    app.cancel_editing_entry();

    assert_eq!(app.edit_hscroll, 0);
    assert_eq!(app.edit_vscroll, 0);
    assert!(!app.editing_entry);
}

#[test]
fn test_view_edit_mode_flag() {
    let mut app = App::new(FormatMode::View);

    // Initially not in View Edit mode
    assert!(!app.view_edit_mode);

    // Simulate entering View Edit mode
    app.view_edit_mode = true;
    assert!(app.view_edit_mode);

    // Cancel editing should reset View Edit mode
    app.cancel_editing_entry();
    assert!(!app.view_edit_mode);
}

#[test]
fn test_horizontal_scroll_with_cursor() {
    let mut app = App::new(FormatMode::View);
    app.editing_entry = true;
    app.edit_field_editing_mode = true;
    app.edit_field_index = 0; // name field

    // Simulate a long field
    app.edit_buffer = vec![
        "This is a very long name that should require horizontal scrolling to view completely".to_string(),
        "context".to_string(),
        "url".to_string(),
        "percentage".to_string(),
        "Exit".to_string(),
    ];

    // Move cursor to end
    app.edit_cursor_pos = app.edit_buffer[0].chars().count();

    // Call ensure_overlay_cursor_visible to trigger scroll
    app.ensure_overlay_cursor_visible();

    // Should have scrolled horizontally
    assert!(app.edit_hscroll > 0);
}

#[test]
fn test_vertical_scroll_in_view_edit_mode() {
    let mut app = App::new(FormatMode::View);
    app.editing_entry = true;
    app.edit_field_editing_mode = true;
    app.edit_field_index = 1; // context field
    app.view_edit_mode = true;

    // Simulate multi-line context with \n
    app.edit_buffer = vec![
        "date".to_string(),
        "Line 1\\nLine 2\\nLine 3\\nLine 4\\nLine 5\\nLine 6\\nLine 7\\nLine 8".to_string(),
        "Exit".to_string(),
    ];

    // Move cursor to last line (after "Line 8")
    app.edit_cursor_pos = app.edit_buffer[1].chars().count();

    // Call ensure_overlay_cursor_visible to trigger scroll
    app.ensure_overlay_cursor_visible();

    // Should have scrolled vertically
    assert!(app.edit_vscroll > 0);
}

#[test]
fn test_scroll_reset_on_field_change() {
    let mut app = App::new(FormatMode::View);
    app.editing_entry = true;
    app.edit_hscroll = 10;
    app.edit_vscroll = 5;
    app.edit_field_index = 1;

    // Simulate moving to different field (this happens in input.rs)
    app.edit_field_index = 2;
    app.edit_cursor_pos = 0;
    app.edit_hscroll = 0;
    app.edit_vscroll = 0;

    assert_eq!(app.edit_hscroll, 0);
    assert_eq!(app.edit_vscroll, 0);
}

#[test]
fn test_cursor_position_tracking() {
    let mut app = App::new(FormatMode::View);
    app.editing_entry = true;
    app.edit_field_editing_mode = true;

    app.edit_buffer = vec![
        "name".to_string(),
        "context".to_string(),
        "Exit".to_string(),
    ];

    // Test cursor at start
    app.edit_cursor_pos = 0;
    assert_eq!(app.edit_cursor_pos, 0);

    // Test cursor at end of field
    app.edit_field_index = 1;
    let field_len = app.edit_buffer[1].chars().count();
    app.edit_cursor_pos = field_len;
    assert_eq!(app.edit_cursor_pos, field_len);
}

#[test]
fn test_field_selection_mode_renders_newlines() {
    let mut app = App::new(FormatMode::View);
    app.editing_entry = true;
    app.edit_field_editing_mode = false; // Field selection mode
    app.view_edit_mode = false;
    app.edit_field_index = 1; // context field

    // Simulate context with \n
    app.edit_buffer = vec![
        "date".to_string(),
        "Line 1\\nLine 2\\nLine 3".to_string(),
        "Exit".to_string(),
    ];

    // In field selection mode, context should render newlines
    // This is tested by checking the flags
    assert!(!app.edit_field_editing_mode);
    assert!(!app.view_edit_mode);
}

#[test]
fn test_normal_mode_shows_literal_newlines() {
    let mut app = App::new(FormatMode::View);
    app.editing_entry = true;
    app.edit_field_editing_mode = true; // Field editing mode (normal)
    app.edit_insert_mode = false;
    app.view_edit_mode = false;
    app.edit_field_index = 1; // context field

    // Simulate context with \n
    app.edit_buffer = vec![
        "date".to_string(),
        "Line 1\\nLine 2\\nLine 3".to_string(),
        "Exit".to_string(),
    ];

    // In normal/insert mode, \n should be shown literally
    assert!(app.edit_field_editing_mode);
    assert!(!app.view_edit_mode);
    assert!(!app.edit_insert_mode);
}

#[test]
fn test_insert_mode_shows_literal_newlines() {
    let mut app = App::new(FormatMode::View);
    app.editing_entry = true;
    app.edit_field_editing_mode = true; // Field editing mode (insert)
    app.edit_insert_mode = true;
    app.view_edit_mode = false;
    app.edit_field_index = 1; // context field

    // Simulate context with \n
    app.edit_buffer = vec![
        "date".to_string(),
        "Line 1\\nLine 2\\nLine 3".to_string(),
        "Exit".to_string(),
    ];

    // In insert mode, \n should be shown literally
    assert!(app.edit_field_editing_mode);
    assert!(!app.view_edit_mode);
    assert!(app.edit_insert_mode);
}

#[test]
fn test_view_edit_mode_renders_newlines() {
    let mut app = App::new(FormatMode::View);
    app.editing_entry = true;
    app.edit_field_editing_mode = true;
    app.edit_insert_mode = true;
    app.view_edit_mode = true; // View Edit mode
    app.edit_field_index = 1; // context field

    // Simulate context with \n
    app.edit_buffer = vec![
        "date".to_string(),
        "Line 1\\nLine 2\\nLine 3".to_string(),
        "Exit".to_string(),
    ];

    // In view edit mode, context should render newlines
    assert!(app.edit_field_editing_mode);
    assert!(app.view_edit_mode);
}