Codex Handbook
tui/src/chatwidget/tests/status_surface_previews.rs 392 lines
use super::*;use crate::bottom_pane::preview_line_for_title_items;use pretty_assertions::assert_eq;use ratatui::text::Line;fn line_text(line: Line<'static>) -> String {    line.spans        .into_iter()        .map(|span| span.content.into_owned())        .collect()}fn status_preview_line_option(chat: &mut ChatWidget, items: &[StatusLineItem]) -> Option<String> {    let preview_data = chat.status_surface_preview_data();    preview_data        .status_line_for_items(items.iter().copied(), /*use_theme_colors*/ true)        .map(line_text)}fn status_preview_line(chat: &mut ChatWidget, items: &[StatusLineItem]) -> String {    status_preview_line_option(chat, items).expect("status preview line")}fn title_preview_line(chat: &mut ChatWidget, items: &[TerminalTitleItem]) -> String {    let preview_data = chat.terminal_title_preview_data();    let preview =        preview_line_for_title_items(items, &preview_data).expect("terminal title preview line");    line_text(preview)}fn combined_preview_snapshot(    chat: &mut ChatWidget,    status_items: &[StatusLineItem],    title_items: &[TerminalTitleItem],) -> String {    normalize_snapshot_paths(format!(        "status line: {}\nterminal title: {}",        status_preview_line(chat, status_items),        title_preview_line(chat, title_items),    ))}fn status_line_popup_snapshot(chat: &mut ChatWidget) -> String {    chat.open_status_line_setup();    normalize_snapshot_paths(strip_osc8_for_snapshot(&render_bottom_popup(        chat, /*width*/ 100,    )))}fn terminal_title_popup_snapshot(chat: &mut ChatWidget) -> String {    chat.open_terminal_title_setup();    normalize_snapshot_paths(strip_osc8_for_snapshot(&render_bottom_popup(        chat, /*width*/ 100,    )))}fn cache_project_root(chat: &mut ChatWidget, root_name: &str) {    chat.status_line_project_root_name_cache = Some(CachedProjectRootName {        cwd: chat.config.cwd.to_path_buf(),        root_name: Some(root_name.to_string()),    });}fn cache_rate_limit_snapshot(chat: &mut ChatWidget) {    chat.on_rate_limit_snapshot(Some(RateLimitSnapshot {        limit_id: None,        limit_name: None,        primary: Some(RateLimitWindow {            used_percent: 35,            window_duration_mins: Some(30 * 24 * 60),            resets_at: None,        }),        secondary: Some(RateLimitWindow {            used_percent: 50,            window_duration_mins: Some(7 * 24 * 60),            resets_at: None,        }),        credits: None,        individual_limit: None,        plan_type: None,        rate_limit_reached_type: None,    }));}#[tokio::test]async fn status_surface_preview_lines_live_only_snapshot() {    let (mut chat, _rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await;    cache_project_root(&mut chat, "preview-live-root");    chat.status_line_branch = Some("feature/live-preview-branch".to_string());    chat.thread_name = Some("Live preview thread".to_string());    chat.transcript.last_plan_progress = Some((2, 5));    let snapshot = combined_preview_snapshot(        &mut chat,        &[            StatusLineItem::ProjectRoot,            StatusLineItem::GitBranch,            StatusLineItem::ThreadTitle,        ],        &[            TerminalTitleItem::Project,            TerminalTitleItem::Thread,            TerminalTitleItem::GitBranch,            TerminalTitleItem::TaskProgress,        ],    );    assert_chatwidget_snapshot!("status_surface_previews_live_only", snapshot);}#[tokio::test]async fn status_line_setup_popup_live_only_snapshot() {    let (mut chat, _rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await;    cache_project_root(&mut chat, "preview-live-root");    chat.status_line_branch = Some("feature/live-preview-branch".to_string());    chat.thread_name = Some("Live preview thread".to_string());    chat.config.tui_status_line = Some(vec![        "project-name".to_string(),        "git-branch".to_string(),        "thread-title".to_string(),    ]);    assert_chatwidget_snapshot!(        "status_line_setup_popup_live_only",        status_line_popup_snapshot(&mut chat)    );}#[tokio::test]async fn status_surface_preview_lines_hardcoded_only_snapshot() {    let (mut chat, _rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await;    let snapshot = combined_preview_snapshot(        &mut chat,        &[            StatusLineItem::ProjectRoot,            StatusLineItem::GitBranch,            StatusLineItem::ThreadTitle,            StatusLineItem::Permissions,            StatusLineItem::ApprovalMode,        ],        &[            TerminalTitleItem::Thread,            TerminalTitleItem::GitBranch,            TerminalTitleItem::TaskProgress,        ],    );    assert_chatwidget_snapshot!("status_surface_previews_hardcoded_only", snapshot);}#[tokio::test]async fn thread_title_falls_back_to_thread_id_when_unnamed() {    let (mut chat, _rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await;    let thread_id = ThreadId::new();    chat.thread_id = Some(thread_id);    assert_eq!(        status_preview_line(&mut chat, &[StatusLineItem::ThreadTitle]),        thread_id.to_string()    );    assert_eq!(        title_preview_line(&mut chat, &[TerminalTitleItem::Thread]),        thread_id.to_string()    );}#[tokio::test]async fn status_line_setup_popup_hardcoded_only_snapshot() {    let (mut chat, _rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await;    chat.config.tui_status_line = Some(vec![        "project-name".to_string(),        "git-branch".to_string(),        "thread-title".to_string(),    ]);    assert_chatwidget_snapshot!(        "status_line_setup_popup_hardcoded_only",        status_line_popup_snapshot(&mut chat)    );}#[tokio::test]async fn status_surface_preview_lines_mixed_snapshot() {    let (mut chat, _rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await;    chat.status_line_branch = Some("feature/mixed-preview".to_string());    chat.thread_name = Some("Mixed preview thread".to_string());    let snapshot = combined_preview_snapshot(        &mut chat,        &[            StatusLineItem::ProjectRoot,            StatusLineItem::GitBranch,            StatusLineItem::ThreadTitle,        ],        &[            TerminalTitleItem::Project,            TerminalTitleItem::Thread,            TerminalTitleItem::TaskProgress,        ],    );    assert_chatwidget_snapshot!("status_surface_previews_mixed", snapshot);}#[tokio::test]async fn status_surface_preview_lines_rate_limits_snapshot() {    let (mut chat, _rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await;    cache_rate_limit_snapshot(&mut chat);    let snapshot = combined_preview_snapshot(        &mut chat,        &[StatusLineItem::FiveHourLimit, StatusLineItem::WeeklyLimit],        &[            TerminalTitleItem::FiveHourLimit,            TerminalTitleItem::WeeklyLimit,        ],    );    assert_chatwidget_snapshot!("status_surface_previews_rate_limits", snapshot);}#[tokio::test]async fn status_surface_preview_omits_unavailable_rate_limit_items() {    let (mut chat, _rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await;    chat.on_rate_limit_snapshot(Some(RateLimitSnapshot {        limit_id: None,        limit_name: None,        primary: Some(RateLimitWindow {            used_percent: 9,            window_duration_mins: Some(7 * 24 * 60),            resets_at: None,        }),        secondary: None,        credits: None,        individual_limit: None,        plan_type: None,        rate_limit_reached_type: None,    }));    assert_eq!(        status_preview_line_option(&mut chat, &[StatusLineItem::FiveHourLimit]),        None    );    assert_eq!(        status_preview_line(            &mut chat,            &[StatusLineItem::FiveHourLimit, StatusLineItem::WeeklyLimit]        ),        "weekly 91% left"    );    assert_eq!(        title_preview_line(            &mut chat,            &[                TerminalTitleItem::FiveHourLimit,                TerminalTitleItem::WeeklyLimit            ],        ),        "weekly 91% left"    );}#[tokio::test]async fn status_line_setup_popup_rate_limits_snapshot() {    let (mut chat, _rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await;    cache_rate_limit_snapshot(&mut chat);    chat.config.tui_status_line = Some(vec![        "five-hour-limit".to_string(),        "weekly-limit".to_string(),    ]);    assert_chatwidget_snapshot!(        "status_line_setup_popup_rate_limits",        status_line_popup_snapshot(&mut chat)    );}#[tokio::test]async fn status_line_setup_popup_mixed_snapshot() {    let (mut chat, _rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await;    chat.status_line_branch = Some("feature/mixed-preview".to_string());    chat.thread_name = Some("Mixed preview thread".to_string());    chat.config.tui_status_line = Some(vec![        "project-name".to_string(),        "git-branch".to_string(),        "thread-title".to_string(),    ]);    assert_chatwidget_snapshot!(        "status_line_setup_popup_mixed",        status_line_popup_snapshot(&mut chat)    );}#[tokio::test]async fn terminal_title_setup_popup_live_only_snapshot() {    let (mut chat, _rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await;    cache_project_root(&mut chat, "preview-live-root");    chat.status_line_branch = Some("feature/live-preview-branch".to_string());    chat.thread_name = Some("Live preview thread".to_string());    chat.transcript.last_plan_progress = Some((2, 5));    chat.config.tui_terminal_title = Some(vec![        "project-name".to_string(),        "thread-title".to_string(),        "git-branch".to_string(),        "task-progress".to_string(),    ]);    assert_chatwidget_snapshot!(        "terminal_title_setup_popup_live_only",        terminal_title_popup_snapshot(&mut chat)    );}#[tokio::test]async fn terminal_title_setup_popup_hardcoded_only_snapshot() {    let (mut chat, _rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await;    chat.config.tui_terminal_title = Some(vec![        "thread-title".to_string(),        "git-branch".to_string(),        "task-progress".to_string(),    ]);    assert_chatwidget_snapshot!(        "terminal_title_setup_popup_hardcoded_only",        terminal_title_popup_snapshot(&mut chat)    );}#[tokio::test]async fn terminal_title_setup_popup_mixed_snapshot() {    let (mut chat, _rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await;    chat.thread_name = Some("Mixed preview thread".to_string());    chat.config.tui_terminal_title = Some(vec![        "project-name".to_string(),        "thread-title".to_string(),        "task-progress".to_string(),    ]);    assert_chatwidget_snapshot!(        "terminal_title_setup_popup_mixed",        terminal_title_popup_snapshot(&mut chat)    );}#[tokio::test]async fn terminal_title_setup_popup_rate_limits_snapshot() {    let (mut chat, _rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await;    cache_rate_limit_snapshot(&mut chat);    chat.config.tui_terminal_title = Some(vec![        "five-hour-limit".to_string(),        "weekly-limit".to_string(),    ]);    assert_chatwidget_snapshot!(        "terminal_title_setup_popup_rate_limits",        terminal_title_popup_snapshot(&mut chat)    );}#[tokio::test]async fn missing_project_root_uses_different_status_and_title_preview_sources() {    let (mut chat, _rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await;    let status_preview = status_preview_line(&mut chat, &[StatusLineItem::ProjectRoot]);    let title_preview = title_preview_line(&mut chat, &[TerminalTitleItem::Project]);    assert_eq!(status_preview, "my-project");    assert_eq!(title_preview, "project");}#[tokio::test]async fn terminal_title_preview_uses_title_truncation_for_live_values() {    let (mut chat, _rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await;    let long_thread = "This thread title is intentionally much longer than forty-eight characters";    let long_branch = "feature/this-branch-name-is-intentionally-longer-than-thirty-two";    chat.thread_name = Some(long_thread.to_string());    chat.status_line_branch = Some(long_branch.to_string());    let preview = title_preview_line(        &mut chat,        &[TerminalTitleItem::Thread, TerminalTitleItem::GitBranch],    );    let truncated_thread =        ChatWidget::truncate_terminal_title_part(long_thread.to_string(), /*max_chars*/ 48);    let truncated_branch =        ChatWidget::truncate_terminal_title_part(long_branch.to_string(), /*max_chars*/ 32);    assert_eq!(preview, format!("{truncated_thread} | {truncated_branch}"));}