test(tui): cover approval input after message drain
This commit is contained in:
@@ -1940,12 +1940,8 @@ async fn run_event_loop(
|
||||
} else {
|
||||
let tool_input = input;
|
||||
|
||||
if tool_name == "apply_patch" {
|
||||
maybe_add_patch_preview(app, &tool_input);
|
||||
}
|
||||
|
||||
// Create approval request and show overlay
|
||||
let request = ApprovalRequest::new(
|
||||
push_approval_request_view(
|
||||
app,
|
||||
&id,
|
||||
&tool_name,
|
||||
&description,
|
||||
@@ -1961,8 +1957,6 @@ async fn run_event_loop(
|
||||
"mode": app.mode.label(),
|
||||
}),
|
||||
);
|
||||
app.view_stack
|
||||
.push(ApprovalView::new_for_locale(request, app.ui_locale));
|
||||
app.status_message = Some(format!(
|
||||
"Approval required for '{tool_name}': {description}"
|
||||
));
|
||||
@@ -6399,6 +6393,23 @@ async fn handle_view_events(
|
||||
Ok(false)
|
||||
}
|
||||
|
||||
fn push_approval_request_view(
|
||||
app: &mut App,
|
||||
id: &str,
|
||||
tool_name: &str,
|
||||
description: &str,
|
||||
tool_input: &serde_json::Value,
|
||||
approval_key: &str,
|
||||
) {
|
||||
if tool_name == "apply_patch" {
|
||||
maybe_add_patch_preview(app, tool_input);
|
||||
}
|
||||
|
||||
let request = ApprovalRequest::new(id, tool_name, description, tool_input, approval_key);
|
||||
app.view_stack
|
||||
.push(ApprovalView::new_for_locale(request, app.ui_locale));
|
||||
}
|
||||
|
||||
struct ApprovalDecisionEvent {
|
||||
tool_id: String,
|
||||
tool_name: String,
|
||||
|
||||
@@ -5202,6 +5202,49 @@ fn message_complete_drain_preserves_thinking_when_thinking_complete_lost() {
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn approval_prompt_uses_event_input_after_message_complete_drain() {
|
||||
let mut app = create_test_app();
|
||||
app.pending_tool_uses.push((
|
||||
"tool-1".to_string(),
|
||||
"exec_shell".to_string(),
|
||||
serde_json::json!({"command": "stale value from drained list"}),
|
||||
));
|
||||
|
||||
// Mirror the old race: MessageComplete drains pending tool uses before
|
||||
// ApprovalRequired is handled. The approval modal must still show the
|
||||
// non-empty input carried directly on the ApprovalRequired event.
|
||||
app.pending_tool_uses.clear();
|
||||
|
||||
let event_input = serde_json::json!({
|
||||
"command": "cargo test -p codewhale-tui approval",
|
||||
"workdir": "/repo",
|
||||
});
|
||||
push_approval_request_view(
|
||||
&mut app,
|
||||
"tool-1",
|
||||
"exec_shell",
|
||||
"Run cargo tests",
|
||||
&event_input,
|
||||
"approval-key",
|
||||
);
|
||||
|
||||
let mut view = app.view_stack.pop().expect("approval view");
|
||||
let approval = view
|
||||
.as_any_mut()
|
||||
.downcast_mut::<ApprovalView>()
|
||||
.expect("approval view");
|
||||
let action = approval.handle_key(KeyEvent::new(KeyCode::Char('v'), KeyModifiers::NONE));
|
||||
let ViewAction::Emit(ViewEvent::OpenTextPager { content, .. }) = action else {
|
||||
panic!("expected approval params pager");
|
||||
};
|
||||
|
||||
assert!(content.contains("cargo test -p codewhale-tui approval"));
|
||||
assert!(content.contains("/repo"));
|
||||
assert!(!content.contains("stale value from drained list"));
|
||||
assert_ne!(content.trim(), "{}");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn second_thinking_block_appends_new_entry_in_same_active_cell() {
|
||||
// Real V4 turns can emit Thinking → Tool → Thinking → Tool before any
|
||||
|
||||
Reference in New Issue
Block a user