diff options
| author | JJ Liebig <jonathan.liebig@gmail.com> | 2026-09-13 21:14:00 +0400 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2026-09-13 19:14:00 +0200 |
| commit | 3834fd3d0f77a809cf3e394fca31fd036d3173dd (patch) | |
| tree | b24702d12d9b951a8bb6cbe2a4386ec3b3b42152 /src/client/shell/tests/agents_worktrees_notifications.rs | |
| parent | f0cb0e0683953e7dbc32d911268931f25d3e448f (diff) | |
fix: auto-expire worktree action error banners (#4063)
* fix: auto-expire worktree action error banners
refs #1827
* fix: restart endpoint error timeout on repeated errors
Route every transient client-side action error through a setter that installs a fresh deadline, so an identical repeated message cannot inherit an older, nearly-expired deadline.
refs #1827
* test: derive endpoint error expiry assertions from stored deadline
refs #1827
Diffstat (limited to 'src/client/shell/tests/agents_worktrees_notifications.rs')
| -rw-r--r-- | src/client/shell/tests/agents_worktrees_notifications.rs | 65 |
1 files changed, 65 insertions, 0 deletions
diff --git a/src/client/shell/tests/agents_worktrees_notifications.rs b/src/client/shell/tests/agents_worktrees_notifications.rs index 0b936903..c89991b1 100644 --- a/src/client/shell/tests/agents_worktrees_notifications.rs +++ b/src/client/shell/tests/agents_worktrees_notifications.rs @@ -1088,6 +1088,71 @@ fn unavailable_worktree_create_does_not_wedge_the_overlay() { } #[test] +fn worktree_action_errors_expire_without_more_input() { + let mut state = ClientShellState::new(ClientShellConfig::from_config(&Config::default())); + state.set_snapshot(Box::new(snapshot())); + state.set_pane_surface(surface()); + + let mut guard = ClientShellInput::default(); + state.record_binding( + crate::input::KeybindMatch::Action(crate::input::KeybindAction::RemoveWorktree), + &mut guard, + ); + let message = "This workspace is not a Herdr-managed worktree checkout."; + assert_eq!(state.endpoint_error.as_deref(), Some(message)); + + let deadline = state.endpoint_error_deadline.expect("deadline"); + assert!(!state.tick_endpoint_error(deadline - std::time::Duration::from_secs(1))); + assert_eq!(state.endpoint_error.as_deref(), Some(message)); + + assert!(state.tick_endpoint_error(deadline + std::time::Duration::from_millis(1))); + assert!(state.endpoint_error.is_none()); + + // A repeated identical message must start a fresh lifetime instead of + // inheriting the earlier deadline. + let before_repeat = std::time::Instant::now(); + state.set_endpoint_error(message); + assert!( + state.endpoint_error_deadline.expect("deadline") + >= before_repeat + std::time::Duration::from_secs(5) + ); +} + +#[test] +fn worktree_prepare_rejection_notice_expires() { + let mut state = ClientShellState::new(ClientShellConfig::from_config(&Config::default())); + state.set_snapshot(Box::new(snapshot())); + state.set_pane_surface(surface()); + let mut prepare = ClientShellInput::default(); + state.record_binding( + crate::input::KeybindMatch::Action(crate::input::KeybindAction::NewWorktree), + &mut prepare, + ); + let [ClientShellAction::Endpoint { request, .. }] = &prepare.actions[..] else { + panic!("new worktree should prepare through worktree.list"); + }; + let request_id = request.id.clone(); + state.handle_endpoint_result( + "boot-1", + &request_id, + Err(ClientShellEndpointError { + code: Some("not_git_worktree".into()), + message: "Herdr worktree actions require a workspace inside a Git work tree".into(), + }), + ); + let notice = state + .visible_endpoint_notice + .as_ref() + .expect("rejection notice"); + assert!(notice.key.code.contains("not_git_worktree")); + let deadline = notice.deadline; + + let (_, repaint) = state.tick_notifications(deadline + std::time::Duration::from_millis(1)); + assert!(repaint); + assert!(state.visible_endpoint_notice.is_none()); +} + +#[test] fn worktree_open_filters_and_clicks_a_stable_public_entry() { let mut state = ClientShellState::new(ClientShellConfig::from_config(&Config::default())); state.set_snapshot(Box::new(snapshot())); |
