diff --git a/agentydragon/README.md b/agentydragon/README.md index f75221ef47..3190703581 100644 --- a/agentydragon/README.md +++ b/agentydragon/README.md @@ -43,6 +43,9 @@ This file documents the changes introduced on the `agentydragon` branch - Updated Markdown rendering in chat UI and logs to honor compact mode globally (diffs, docs, help messages). - Added unit tests covering H1–H6 heading spacing for both compact and default modes. +## codex-rs/tui: tests for interactive prompt overlay during execution + - Added unit tests in `tui/src/bottom_pane/mod.rs` to verify that character input and Enter during `is_task_running` forwards input to the composer, maintains the status indicator overlay, emits redraw events, and that the overlay is removed when the task completes. + ## Documentation tasks Tasks live under `agentydragon/tasks/` as individual Markdown files. Please update each task’s **Status** and **Implementation** sections in place rather than maintaining a static list here. diff --git a/agentydragon/tasks/36-tests-interactive-prompt-execution.md b/agentydragon/tasks/36-tests-interactive-prompt-execution.md index 076c2914a4..9e0b8ae279 100644 --- a/agentydragon/tasks/36-tests-interactive-prompt-execution.md +++ b/agentydragon/tasks/36-tests-interactive-prompt-execution.md @@ -1,16 +1,16 @@ +++ id = "36" title = "Add Tests for Interactive Prompting While Executing" -status = "Not started" +status = "Done" dependencies = "06,13" # Rationale: depends on Tasks 06 and 13 for external editor and interactive prompt support -last_updated = "2025-06-25T04:45:29Z" +last_updated = "2025-06-25T11:05:55Z" +++ > *This task is specific to codex-rs.* ## Status -**General Status**: Not started +**General Status**: Done **Summary**: Follow-up to Task 13; add unit tests for interactive prompt overlay during execution. ## Goal @@ -25,11 +25,14 @@ Write tests that verify `BottomPane::handle_key_event` forwards input to the com ## Implementation -**How it was implemented** -*(Not implemented yet)* +**Planned Approach** -**How it works** -*(Not implemented yet)* +- Use existing `make_pane` and `make_pane_and_rx` helpers to create a `BottomPane` in a running-task state. +- Write unit tests in `tui/src/bottom_pane/mod.rs` that verify: + - Typing alphanumeric characters while `is_task_running == true` appends to the composer, maintains the `StatusIndicatorView` overlay, and emits a `AppEvent::Redraw`. + - Pressing Enter returns `InputResult::Submitted` with the buffered text, clears the composer, retains the overlay, and triggers a redraw. + - Calling `set_task_running(false)` removes the status indicator overlay. +- Follow existing patterns from the tests in `user_approval_widget.rs` and `set_title_view.rs`. ## Notes diff --git a/codex-rs/tui/src/bottom_pane/mod.rs b/codex-rs/tui/src/bottom_pane/mod.rs index 446fbb11be..ebbc8f86a4 100644 --- a/codex-rs/tui/src/bottom_pane/mod.rs +++ b/codex-rs/tui/src/bottom_pane/mod.rs @@ -249,6 +249,8 @@ impl WidgetRef for &BottomPane<'_> { mod tests { use super::*; use crossterm::event::{KeyCode, KeyEvent, KeyModifiers}; + use std::sync::mpsc; + use crate::app_event::AppEvent; /// Construct a BottomPane with default parameters for testing. fn make_pane() -> BottomPane<'static> { @@ -261,6 +263,18 @@ mod tests { }) } + /// Construct a BottomPane and return it along with the associated event receiver. + fn make_pane_and_rx() -> (BottomPane<'static>, mpsc::Receiver) { + let (tx, rx) = mpsc::channel(); + let app_event_tx = AppEventSender::new(tx); + let pane = BottomPane::new(BottomPaneParams { + app_event_tx, + has_input_focus: true, + composer_max_rows: 3, + }); + (pane, rx) + } + #[test] fn forward_input_during_status_indicator() { let mut pane = make_pane(); @@ -276,11 +290,12 @@ mod tests { assert_eq!(content, "h"); // Status indicator overlay remains active assert!(pane.active_view.is_some()); + // The overlay should be a StatusIndicatorView + assert!(pane.active_view.as_mut().unwrap().should_hide_when_task_is_done()); } #[test] fn remove_status_indicator_after_task_complete() { -mod config_reload_view; let mut pane = make_pane(); pane.set_task_running(true); assert!(pane.active_view.is_some()); @@ -288,4 +303,38 @@ mod config_reload_view; // Overlay should be removed when task finishes assert!(pane.active_view.is_none()); } + + #[test] + fn redraw_requested_on_char_input_during_status_indicator() { + let (mut pane, rx) = make_pane_and_rx(); + pane.set_task_running(true); + let key = KeyEvent::new(KeyCode::Char('x'), KeyModifiers::NONE); + let _ = pane.handle_key_event(key); + // Char input should trigger a redraw event + assert_eq!(rx.try_recv(), Ok(AppEvent::Redraw)); + } + + #[test] + fn submit_and_redraw_during_status_indicator() { + let (mut pane, rx) = make_pane_and_rx(); + pane.set_task_running(true); + // Type "hi" + pane.handle_key_event(KeyEvent::new(KeyCode::Char('h'), KeyModifiers::NONE)); + pane.handle_key_event(KeyEvent::new(KeyCode::Char('i'), KeyModifiers::NONE)); + // Drain intermediate redraws + while rx.try_recv().is_ok() {} + // Submit with Enter + let result = pane.handle_key_event(KeyEvent::new(KeyCode::Enter, KeyModifiers::NONE)); + // Should submit the buffered text + assert!(matches!(result, InputResult::Submitted(ref txt) if txt == "hi")); + // Enter should also trigger a redraw + assert_eq!(rx.try_recv(), Ok(AppEvent::Redraw)); + // Overlay remains active until task is marked done + assert!(pane.active_view.is_some()); + // Should still be showing the status indicator overlay + assert!(pane.active_view.as_mut().unwrap().should_hide_when_task_is_done()); + // The composer buffer should be cleared after submission + let content = pane.composer.textarea.lines().join("\n"); + assert_eq!(content, ""); + } }