television 0.15.5

A very fast, portable and hackable fuzzy finder for the terminal
Documentation
//! Tests for CLI input/interaction options: --input, --keybindings, --exact.
//!
//! These tests verify Television's input handling and user interaction features,
//! ensuring users can customize their interaction experience and search behavior.

use tempfile::TempDir;

use super::super::common::*;

/// Tests that the --input flag pre-fills the search box with specified text.
#[test]
fn test_input_prefills_search_box() {
    let mut tester = PtyTester::new();

    // This should start the files channel with "UNIQUE16CHARID" already typed in the search box
    let cmd = tv_local_config_and_cable_with_args(&[
        "files",
        "--input",
        "UNIQUE16CHARID",
    ]);
    let mut child = tester.spawn_command_tui(cmd);

    // Verify the search box contains the pre-filled text
    tester.assert_tui_frame_contains("│> UNIQUE16CHARID");

    // Send Ctrl+C to exit the application gracefully
    tester.send(&ctrl('c'));
    tester.assert_exit_ok(&mut child, DEFAULT_DELAY);
}

/// Tests that custom keybindings override default keyboard shortcuts.
#[test]
fn test_keybindings_override_default() {
    let mut tester = PtyTester::new();

    // This adds a new mapping for the quit action
    let mut child =
        tester.spawn_command_tui(tv_local_config_and_cable_with_args(&[
            "--keybindings",
            "a=\"quit\";ctrl-c=\"no_op\";esc=\"no_op\"",
        ]));

    // Test that ESC no longer quits (default behavior is overridden)
    tester.send(ESC);
    tester.assert_tui_running(&mut child);

    // Test that Ctrl+C no longer quits (default behavior is overridden)
    tester.send(&ctrl('c'));
    tester.assert_tui_running(&mut child);

    // Test that our custom "a" key now quits the application
    tester.send("'a'");
    tester.assert_exit_ok(&mut child, DEFAULT_DELAY);
}

/// Tests that multiple keybinding overrides can be specified simultaneously.
#[test]
fn test_multiple_keybindings_override() {
    let mut tester = PtyTester::new();

    // This sets up two custom keybindings: "a" for quit and Ctrl+T for remote control
    let mut child =
        tester.spawn_command_tui(tv_local_config_and_cable_with_args(&[
            "--keybindings",
            "a=\"quit\";ctrl-x=\"toggle_remote_control\";esc=\"no_op\"",
        ]));

    // Verify ESC doesn't quit (default overridden)
    tester.send(ESC);
    tester.assert_tui_running(&mut child);

    // Test that Ctrl+T opens remote control panel (custom keybinding works)
    tester.send(&ctrl('x'));
    tester.assert_tui_frame_contains("(1) (2) (3)"); // Remote control indicators
    tester.send(&ctrl('t'));

    // Use "a" to quit the application
    tester.send("'a'");
    tester.assert_exit_ok(&mut child, DEFAULT_DELAY);
}

/// Tests that the --exact flag enables exact substring matching instead of fuzzy matching.
#[test]
fn test_exact_matching_enabled() {
    let mut tester = PtyTester::new();
    let tmp_dir = TempDir::new().unwrap();

    // Create initial file to be detected
    std::fs::write(tmp_dir.path().join("UNIQUE16CHARIDfile.txt"), "").unwrap();

    // This enables exact substring matching instead of the default fuzzy matching
    let cmd = tv_local_config_and_cable_with_args(&[
        "files",
        "--exact",
        "--input",
        "UNIQUE16CHARIDfile",
        tmp_dir.path().to_str().unwrap(),
    ]);
    let mut child = tester.spawn_command_tui(cmd);

    // Verify the TUI started successfully with exact matching enabled
    tester.assert_tui_frame_contains("UNIQUE16CHARIDfile.txt");

    // Send Ctrl+C to exit the application
    tester.send(&ctrl('c'));
    tester.assert_exit_ok(&mut child, DEFAULT_DELAY);
}

#[test]
fn test_exact_matching_enabled_fails() {
    let mut tester = PtyTester::new();
    let tmp_dir = TempDir::new().unwrap();

    // Create initial file to be detected
    std::fs::write(tmp_dir.path().join("UNIQUE16CHARIDfile.txt"), "").unwrap();

    // This enables exact substring matching instead of the default fuzzy matching
    let cmd = tv_local_config_and_cable_with_args(&[
        "files",
        "--exact",
        "--input",
        "UNIQUE16CHARIDfl",
        tmp_dir.path().to_str().unwrap(),
    ]);
    let mut child = tester.spawn_command_tui(cmd);

    // Verify the TUI started successfully with exact matching enabled and no results
    tester.assert_tui_frame_contains("│> UNIQUE16CHARIDfl");
    tester.assert_tui_frame_contains("0 / 0");
    tester.assert_not_tui_frame_contains("UNIQUE16CHARIDfile.txt");

    // Send Ctrl+C to exit the application
    tester.send(&ctrl('c'));
    tester.assert_exit_ok(&mut child, DEFAULT_DELAY);
}

/// Tests that --no-sort keeps results in the source order for selection.
#[test]
fn test_no_sort_preserves_source_order() {
    use std::time::Duration;

    let mut tester = PtyTester::new();

    // The second entry is a stronger fuzzy match for "ab".
    let cmd = tv_local_config_and_cable_with_args(&[
        "--source-command",
        "echo 'a-weak-b'; echo 'ab-strong'",
        "--input",
        "ab",
        "--no-sort",
        "--take-1",
    ]);
    tester.spawn_command(cmd);

    // Use timeout-based assertion because --take-1 waits for loading to
    // complete, which may take longer than the initial spawn delay.
    tester.assert_raw_output_contains_with_timeout(
        "a-weak-b",
        Duration::from_secs(2),
    );
}