mirror of
https://github.com/pchuan98/codex.git
synced 2026-07-01 00:31:56 +08:00
Revert "Option to Notify Workspace Owner When Usage Limit is Reached" (#17391)
Reverts openai/codex#16969 #sev3-2026-04-10-accountscheckversion-500s-for-openai-workspace-7300
This commit is contained in:
committed by
GitHub
Unverified
parent
a3be74143a
commit
930e5adb7e
-6
@@ -1,6 +0,0 @@
|
||||
---
|
||||
source: tui/src/chatwidget/tests/app_server.rs
|
||||
assertion_line: 608
|
||||
expression: rendered
|
||||
---
|
||||
■ Your workspace is out of credits. Request more from your workspace owner? [y/N]
|
||||
@@ -128,7 +128,6 @@ pub(super) use codex_protocol::parse_command::ParsedCommand;
|
||||
pub(super) use codex_protocol::plan_tool::PlanItemArg;
|
||||
pub(super) use codex_protocol::plan_tool::StepStatus;
|
||||
pub(super) use codex_protocol::plan_tool::UpdatePlanArgs;
|
||||
pub(super) use codex_protocol::protocol::AddCreditsNudgeEmailStatus;
|
||||
pub(super) use codex_protocol::protocol::AgentMessageDeltaEvent;
|
||||
pub(super) use codex_protocol::protocol::AgentMessageEvent;
|
||||
pub(super) use codex_protocol::protocol::AgentReasoningDeltaEvent;
|
||||
|
||||
@@ -569,117 +569,6 @@ async fn live_app_server_server_overloaded_error_renders_warning() {
|
||||
assert!(!chat.bottom_pane.is_task_running());
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn live_app_server_usage_limit_error_shows_notify_owner_hint() {
|
||||
let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await;
|
||||
chat.update_account_state(
|
||||
/*status_account_display*/ None,
|
||||
/*workspace_role*/ None,
|
||||
Some(false),
|
||||
Some(PlanType::SelfServeBusinessUsageBased),
|
||||
/*has_chatgpt_account*/ true,
|
||||
);
|
||||
chat.on_rate_limit_snapshot(Some(RateLimitSnapshot {
|
||||
limit_id: Some("codex".to_string()),
|
||||
limit_name: Some("codex".to_string()),
|
||||
primary: None,
|
||||
secondary: None,
|
||||
credits: Some(CreditsSnapshot {
|
||||
has_credits: false,
|
||||
unlimited: false,
|
||||
balance: None,
|
||||
}),
|
||||
spend_control: None,
|
||||
plan_type: Some(PlanType::SelfServeBusinessUsageBased),
|
||||
}));
|
||||
|
||||
chat.handle_server_notification(
|
||||
ServerNotification::Error(ErrorNotification {
|
||||
error: AppServerTurnError {
|
||||
message: "The usage limit has been reached".to_string(),
|
||||
codex_error_info: Some(CodexErrorInfo::UsageLimitExceeded.into()),
|
||||
additional_details: None,
|
||||
},
|
||||
will_retry: false,
|
||||
thread_id: "thread-1".to_string(),
|
||||
turn_id: "turn-1".to_string(),
|
||||
}),
|
||||
/*replay_kind*/ None,
|
||||
);
|
||||
|
||||
let cells = drain_insert_history(&mut rx);
|
||||
assert_eq!(cells.len(), 1);
|
||||
let rendered = lines_to_single_string(&cells[0]);
|
||||
assert!(
|
||||
rendered.contains("Your workspace is out of credits."),
|
||||
"expected usage-limit error, got {rendered:?}"
|
||||
);
|
||||
assert!(
|
||||
rendered.contains("Request more from your workspace owner? [y/N]"),
|
||||
"expected workspace-owner prompt, got {rendered:?}"
|
||||
);
|
||||
let popup = render_bottom_popup(&chat, /*width*/ 80);
|
||||
assert!(
|
||||
popup.contains("Request more credits from your workspace owner?"),
|
||||
"expected workspace-owner confirmation popup, got {popup:?}"
|
||||
);
|
||||
assert_chatwidget_snapshot!(
|
||||
"live_app_server_usage_limit_error_shows_notify_owner_hint",
|
||||
rendered
|
||||
);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn live_app_server_usage_limit_error_shows_spend_cap_hint() {
|
||||
let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await;
|
||||
chat.update_account_state(
|
||||
/*status_account_display*/ None,
|
||||
/*workspace_role*/ None,
|
||||
Some(false),
|
||||
Some(PlanType::SelfServeBusinessUsageBased),
|
||||
/*has_chatgpt_account*/ true,
|
||||
);
|
||||
chat.on_rate_limit_snapshot(Some(RateLimitSnapshot {
|
||||
limit_id: Some("codex".to_string()),
|
||||
limit_name: Some("codex".to_string()),
|
||||
primary: None,
|
||||
secondary: None,
|
||||
credits: Some(CreditsSnapshot {
|
||||
has_credits: true,
|
||||
unlimited: false,
|
||||
balance: None,
|
||||
}),
|
||||
spend_control: Some(codex_protocol::protocol::SpendControlSnapshot { reached: true }),
|
||||
plan_type: Some(PlanType::SelfServeBusinessUsageBased),
|
||||
}));
|
||||
|
||||
chat.handle_server_notification(
|
||||
ServerNotification::Error(ErrorNotification {
|
||||
error: AppServerTurnError {
|
||||
message: "The usage limit has been reached".to_string(),
|
||||
codex_error_info: Some(CodexErrorInfo::UsageLimitExceeded.into()),
|
||||
additional_details: None,
|
||||
},
|
||||
will_retry: false,
|
||||
thread_id: "thread-1".to_string(),
|
||||
turn_id: "turn-1".to_string(),
|
||||
}),
|
||||
/*replay_kind*/ None,
|
||||
);
|
||||
|
||||
let cells = drain_insert_history(&mut rx);
|
||||
assert_eq!(cells.len(), 1);
|
||||
let rendered = lines_to_single_string(&cells[0]);
|
||||
assert!(
|
||||
rendered.contains("Your workspace has reached its spend cap."),
|
||||
"expected spend-cap error, got {rendered:?}"
|
||||
);
|
||||
assert!(
|
||||
!rendered.contains("Request more from your workspace owner? [y/N]"),
|
||||
"expected spend-cap guidance instead of workspace-owner prompt, got {rendered:?}"
|
||||
);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn live_app_server_invalid_thread_name_update_is_ignored() {
|
||||
let (mut chat, _rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await;
|
||||
|
||||
@@ -104,7 +104,6 @@ pub(super) fn snapshot(percent: f64) -> RateLimitSnapshot {
|
||||
}),
|
||||
secondary: None,
|
||||
credits: None,
|
||||
spend_control: None,
|
||||
plan_type: None,
|
||||
}
|
||||
}
|
||||
@@ -190,8 +189,6 @@ pub(super) async fn make_chatwidget_manual(
|
||||
current_collaboration_mode,
|
||||
active_collaboration_mask,
|
||||
has_chatgpt_account: false,
|
||||
workspace_role: None,
|
||||
is_workspace_owner: None,
|
||||
model_catalog,
|
||||
session_telemetry,
|
||||
session_header: SessionHeader::new(resolved_model.clone()),
|
||||
@@ -202,8 +199,6 @@ pub(super) async fn make_chatwidget_manual(
|
||||
refreshing_status_outputs: Vec::new(),
|
||||
next_status_refresh_request_id: 0,
|
||||
plan_type: None,
|
||||
notify_workspace_owner_in_flight: false,
|
||||
pending_workspace_owner_notification_prompt: false,
|
||||
rate_limit_warnings: RateLimitWarningState::default(),
|
||||
rate_limit_switch_prompt: RateLimitSwitchPromptState::default(),
|
||||
adaptive_chunking: crate::streaming::chunking::AdaptiveChunkingPolicy::default(),
|
||||
|
||||
@@ -1245,8 +1245,6 @@ async fn collaboration_modes_defaults_to_code_on_startup() {
|
||||
feedback: codex_feedback::CodexFeedback::new(),
|
||||
is_first_run: true,
|
||||
status_account_display: None,
|
||||
initial_workspace_role: None,
|
||||
initial_is_workspace_owner: None,
|
||||
initial_plan_type: None,
|
||||
model: Some(resolved_model.clone()),
|
||||
startup_tooltip_override: None,
|
||||
|
||||
@@ -71,8 +71,6 @@ async fn experimental_mode_plan_is_ignored_on_startup() {
|
||||
feedback: codex_feedback::CodexFeedback::new(),
|
||||
is_first_run: true,
|
||||
status_account_display: None,
|
||||
initial_workspace_role: None,
|
||||
initial_is_workspace_owner: None,
|
||||
initial_plan_type: None,
|
||||
model: Some(resolved_model.clone()),
|
||||
startup_tooltip_override: None,
|
||||
|
||||
@@ -130,8 +130,6 @@ async fn helpers_are_available_and_do_not_panic() {
|
||||
feedback: codex_feedback::CodexFeedback::new(),
|
||||
is_first_run: true,
|
||||
status_account_display: None,
|
||||
initial_workspace_role: None,
|
||||
initial_is_workspace_owner: None,
|
||||
initial_plan_type: None,
|
||||
model: Some(resolved_model),
|
||||
startup_tooltip_override: None,
|
||||
@@ -236,7 +234,6 @@ async fn rate_limit_snapshot_keeps_prior_credits_when_missing_from_headers() {
|
||||
unlimited: false,
|
||||
balance: Some("17.5".to_string()),
|
||||
}),
|
||||
spend_control: None,
|
||||
plan_type: None,
|
||||
}));
|
||||
let initial_balance = chat
|
||||
@@ -256,7 +253,6 @@ async fn rate_limit_snapshot_keeps_prior_credits_when_missing_from_headers() {
|
||||
}),
|
||||
secondary: None,
|
||||
credits: None,
|
||||
spend_control: None,
|
||||
plan_type: None,
|
||||
}));
|
||||
|
||||
@@ -295,7 +291,6 @@ async fn rate_limit_snapshot_updates_and_retains_plan_type() {
|
||||
resets_at: None,
|
||||
}),
|
||||
credits: None,
|
||||
spend_control: None,
|
||||
plan_type: Some(PlanType::Plus),
|
||||
}));
|
||||
assert_eq!(chat.plan_type, Some(PlanType::Plus));
|
||||
@@ -314,7 +309,6 @@ async fn rate_limit_snapshot_updates_and_retains_plan_type() {
|
||||
resets_at: Some(234),
|
||||
}),
|
||||
credits: None,
|
||||
spend_control: None,
|
||||
plan_type: Some(PlanType::Pro),
|
||||
}));
|
||||
assert_eq!(chat.plan_type, Some(PlanType::Pro));
|
||||
@@ -333,7 +327,6 @@ async fn rate_limit_snapshot_updates_and_retains_plan_type() {
|
||||
resets_at: Some(567),
|
||||
}),
|
||||
credits: None,
|
||||
spend_control: None,
|
||||
plan_type: None,
|
||||
}));
|
||||
assert_eq!(chat.plan_type, Some(PlanType::Pro));
|
||||
@@ -357,7 +350,6 @@ async fn rate_limit_snapshots_keep_separate_entries_per_limit_id() {
|
||||
unlimited: false,
|
||||
balance: Some("5.00".to_string()),
|
||||
}),
|
||||
spend_control: None,
|
||||
plan_type: Some(PlanType::Pro),
|
||||
}));
|
||||
|
||||
@@ -371,7 +363,6 @@ async fn rate_limit_snapshots_keep_separate_entries_per_limit_id() {
|
||||
}),
|
||||
secondary: None,
|
||||
credits: None,
|
||||
spend_control: None,
|
||||
plan_type: Some(PlanType::Pro),
|
||||
}));
|
||||
|
||||
@@ -396,101 +387,6 @@ async fn rate_limit_snapshots_keep_separate_entries_per_limit_id() {
|
||||
assert!(other.credits.is_none());
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn core_usage_limit_error_shows_notify_owner_hint() {
|
||||
let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await;
|
||||
chat.update_account_state(
|
||||
/*status_account_display*/ None,
|
||||
/*workspace_role*/ None,
|
||||
Some(false),
|
||||
Some(PlanType::SelfServeBusinessUsageBased),
|
||||
/*has_chatgpt_account*/ true,
|
||||
);
|
||||
chat.on_rate_limit_snapshot(Some(RateLimitSnapshot {
|
||||
limit_id: Some("codex".to_string()),
|
||||
limit_name: Some("codex".to_string()),
|
||||
primary: None,
|
||||
secondary: None,
|
||||
credits: Some(CreditsSnapshot {
|
||||
has_credits: false,
|
||||
unlimited: false,
|
||||
balance: None,
|
||||
}),
|
||||
spend_control: None,
|
||||
plan_type: Some(PlanType::SelfServeBusinessUsageBased),
|
||||
}));
|
||||
|
||||
chat.handle_codex_event(Event {
|
||||
id: "usage-limit".to_string(),
|
||||
msg: EventMsg::Error(ErrorEvent {
|
||||
message: "The usage limit has been reached".to_string(),
|
||||
codex_error_info: Some(CodexErrorInfo::UsageLimitExceeded),
|
||||
}),
|
||||
});
|
||||
|
||||
let cells = drain_insert_history(&mut rx);
|
||||
assert_eq!(cells.len(), 1);
|
||||
let rendered = lines_to_single_string(&cells[0]);
|
||||
assert!(
|
||||
rendered.contains("Your workspace is out of credits."),
|
||||
"expected usage-limit error, got {rendered:?}"
|
||||
);
|
||||
assert!(
|
||||
rendered.contains("Request more from your workspace owner? [y/N]"),
|
||||
"expected workspace-owner prompt, got {rendered:?}"
|
||||
);
|
||||
let popup = render_bottom_popup(&chat, /*width*/ 80);
|
||||
assert!(
|
||||
popup.contains("Request more credits from your workspace owner?"),
|
||||
"expected workspace-owner confirmation popup, got {popup:?}"
|
||||
);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn core_usage_limit_error_shows_spend_cap_hint_when_reached() {
|
||||
let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await;
|
||||
chat.update_account_state(
|
||||
/*status_account_display*/ None,
|
||||
/*workspace_role*/ None,
|
||||
Some(false),
|
||||
Some(PlanType::SelfServeBusinessUsageBased),
|
||||
/*has_chatgpt_account*/ true,
|
||||
);
|
||||
chat.on_rate_limit_snapshot(Some(RateLimitSnapshot {
|
||||
limit_id: Some("codex".to_string()),
|
||||
limit_name: Some("codex".to_string()),
|
||||
primary: None,
|
||||
secondary: None,
|
||||
credits: Some(CreditsSnapshot {
|
||||
has_credits: true,
|
||||
unlimited: false,
|
||||
balance: None,
|
||||
}),
|
||||
spend_control: Some(codex_protocol::protocol::SpendControlSnapshot { reached: true }),
|
||||
plan_type: Some(PlanType::SelfServeBusinessUsageBased),
|
||||
}));
|
||||
|
||||
chat.handle_codex_event(Event {
|
||||
id: "usage-limit".to_string(),
|
||||
msg: EventMsg::Error(ErrorEvent {
|
||||
message: "The usage limit has been reached".to_string(),
|
||||
codex_error_info: Some(CodexErrorInfo::UsageLimitExceeded),
|
||||
}),
|
||||
});
|
||||
|
||||
let cells = drain_insert_history(&mut rx);
|
||||
assert_eq!(cells.len(), 1);
|
||||
let rendered = lines_to_single_string(&cells[0]);
|
||||
assert!(
|
||||
rendered.contains("Your workspace has reached its spend cap."),
|
||||
"expected spend-cap hint, got {rendered:?}"
|
||||
);
|
||||
assert!(
|
||||
!rendered.contains("Request more from your workspace owner? [y/N]"),
|
||||
"expected spend-cap hint instead of workspace-owner prompt, got {rendered:?}"
|
||||
);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn rate_limit_switch_prompt_skips_when_on_lower_cost_model() {
|
||||
let (mut chat, _, _) = make_chatwidget_manual(Some(NUDGE_MODEL_SLUG)).await;
|
||||
@@ -519,7 +415,6 @@ async fn rate_limit_switch_prompt_skips_non_codex_limit() {
|
||||
}),
|
||||
secondary: None,
|
||||
credits: None,
|
||||
spend_control: None,
|
||||
plan_type: None,
|
||||
}));
|
||||
|
||||
|
||||
@@ -120,212 +120,3 @@ async fn status_command_overlapping_refreshes_update_matching_cells_only() {
|
||||
chat.finish_status_rate_limit_refresh(second_request_id);
|
||||
assert!(chat.refreshing_status_outputs.is_empty());
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn usage_limit_error_requests_background_rate_limit_refresh() {
|
||||
let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await;
|
||||
set_chatgpt_auth(&mut chat);
|
||||
chat.update_account_state(
|
||||
/*status_account_display*/ None,
|
||||
/*workspace_role*/ None,
|
||||
Some(false),
|
||||
Some(PlanType::SelfServeBusinessUsageBased),
|
||||
/*has_chatgpt_account*/ true,
|
||||
);
|
||||
|
||||
chat.handle_codex_event(Event {
|
||||
id: "usage-limit".to_string(),
|
||||
msg: EventMsg::Error(ErrorEvent {
|
||||
message: "The usage limit has been reached".to_string(),
|
||||
codex_error_info: Some(CodexErrorInfo::UsageLimitExceeded),
|
||||
}),
|
||||
});
|
||||
|
||||
let events = std::iter::from_fn(|| rx.try_recv().ok()).collect::<Vec<_>>();
|
||||
assert!(
|
||||
events
|
||||
.iter()
|
||||
.any(|event| matches!(event, AppEvent::RefreshRateLimits { .. })),
|
||||
"expected usage-limit errors to trigger a background rate-limit refresh; events: {events:?}"
|
||||
);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn usage_limit_error_opens_workspace_owner_prompt_after_rate_limits_refresh() {
|
||||
let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await;
|
||||
set_chatgpt_auth(&mut chat);
|
||||
chat.update_account_state(
|
||||
/*status_account_display*/ None,
|
||||
/*workspace_role*/ None,
|
||||
Some(false),
|
||||
Some(PlanType::SelfServeBusinessUsageBased),
|
||||
/*has_chatgpt_account*/ true,
|
||||
);
|
||||
|
||||
chat.handle_codex_event(Event {
|
||||
id: "usage-limit".to_string(),
|
||||
msg: EventMsg::Error(ErrorEvent {
|
||||
message: "The usage limit has been reached".to_string(),
|
||||
codex_error_info: Some(CodexErrorInfo::UsageLimitExceeded),
|
||||
}),
|
||||
});
|
||||
|
||||
let events = std::iter::from_fn(|| rx.try_recv().ok()).collect::<Vec<_>>();
|
||||
assert!(
|
||||
events
|
||||
.iter()
|
||||
.any(|event| matches!(event, AppEvent::RefreshRateLimits { .. })),
|
||||
"expected usage-limit errors to request a refresh when rate limits are missing; events: {events:?}"
|
||||
);
|
||||
|
||||
chat.on_rate_limit_snapshot(Some(RateLimitSnapshot {
|
||||
limit_id: Some("codex".to_string()),
|
||||
limit_name: Some("codex".to_string()),
|
||||
primary: None,
|
||||
secondary: None,
|
||||
credits: Some(CreditsSnapshot {
|
||||
has_credits: false,
|
||||
unlimited: false,
|
||||
balance: None,
|
||||
}),
|
||||
spend_control: None,
|
||||
plan_type: Some(PlanType::SelfServeBusinessUsageBased),
|
||||
}));
|
||||
|
||||
let popup = render_bottom_popup(&chat, /*width*/ 80);
|
||||
assert!(
|
||||
popup.contains("Request more credits from your workspace owner?"),
|
||||
"expected workspace-owner prompt after refresh, got: {popup}"
|
||||
);
|
||||
|
||||
chat.handle_key_event(KeyEvent::new(KeyCode::Char('y'), KeyModifiers::NONE));
|
||||
|
||||
assert_matches!(rx.try_recv(), Ok(AppEvent::NotifyWorkspaceOwner));
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn usage_limit_error_opens_workspace_owner_prompt_after_async_workspace_role() {
|
||||
let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await;
|
||||
set_chatgpt_auth(&mut chat);
|
||||
chat.update_account_state(
|
||||
/*status_account_display*/ None,
|
||||
/*workspace_role*/ None,
|
||||
/*is_workspace_owner*/ None,
|
||||
Some(PlanType::SelfServeBusinessUsageBased),
|
||||
/*has_chatgpt_account*/ true,
|
||||
);
|
||||
|
||||
chat.handle_codex_event(Event {
|
||||
id: "usage-limit".to_string(),
|
||||
msg: EventMsg::Error(ErrorEvent {
|
||||
message: "The usage limit has been reached".to_string(),
|
||||
codex_error_info: Some(CodexErrorInfo::UsageLimitExceeded),
|
||||
}),
|
||||
});
|
||||
|
||||
let events = std::iter::from_fn(|| rx.try_recv().ok()).collect::<Vec<_>>();
|
||||
assert!(
|
||||
events
|
||||
.iter()
|
||||
.any(|event| matches!(event, AppEvent::RefreshRateLimits { .. })),
|
||||
"expected usage-limit errors to request a refresh when rate limits are missing; events: {events:?}"
|
||||
);
|
||||
|
||||
chat.on_rate_limit_snapshot(Some(RateLimitSnapshot {
|
||||
limit_id: Some("codex".to_string()),
|
||||
limit_name: Some("codex".to_string()),
|
||||
primary: None,
|
||||
secondary: None,
|
||||
credits: Some(CreditsSnapshot {
|
||||
has_credits: false,
|
||||
unlimited: false,
|
||||
balance: None,
|
||||
}),
|
||||
spend_control: None,
|
||||
plan_type: Some(PlanType::SelfServeBusinessUsageBased),
|
||||
}));
|
||||
|
||||
let popup = render_bottom_popup(&chat, /*width*/ 80);
|
||||
assert!(
|
||||
!popup.contains("Request more credits from your workspace owner?"),
|
||||
"expected no prompt before the async workspace role update, got: {popup}"
|
||||
);
|
||||
|
||||
chat.update_account_state(
|
||||
/*status_account_display*/ None,
|
||||
Some(AppServerWorkspaceRole::StandardUser),
|
||||
/*is_workspace_owner*/ None,
|
||||
Some(PlanType::SelfServeBusinessUsageBased),
|
||||
/*has_chatgpt_account*/ true,
|
||||
);
|
||||
|
||||
let popup = render_bottom_popup(&chat, /*width*/ 80);
|
||||
assert!(
|
||||
popup.contains("Request more credits from your workspace owner?"),
|
||||
"expected workspace-owner prompt after async workspace role, got: {popup}"
|
||||
);
|
||||
|
||||
chat.handle_key_event(KeyEvent::new(KeyCode::Char('y'), KeyModifiers::NONE));
|
||||
|
||||
assert_matches!(rx.try_recv(), Ok(AppEvent::NotifyWorkspaceOwner));
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn notify_workspace_owner_success_adds_confirmation_message() {
|
||||
let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await;
|
||||
chat.start_notify_workspace_owner();
|
||||
|
||||
chat.finish_notify_workspace_owner(Ok(AddCreditsNudgeEmailStatus::Sent));
|
||||
|
||||
let cells = drain_insert_history(&mut rx);
|
||||
assert_eq!(cells.len(), 1, "expected one confirmation message");
|
||||
let rendered = lines_to_single_string(&cells[0]);
|
||||
assert!(
|
||||
rendered.contains("Workspace owner notified."),
|
||||
"expected success message, got {rendered:?}"
|
||||
);
|
||||
assert!(
|
||||
!chat.notify_workspace_owner_in_flight,
|
||||
"notify-owner state should clear after success"
|
||||
);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn notify_workspace_owner_cooldown_adds_info_message() {
|
||||
let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await;
|
||||
chat.start_notify_workspace_owner();
|
||||
|
||||
chat.finish_notify_workspace_owner(Ok(AddCreditsNudgeEmailStatus::CooldownActive));
|
||||
|
||||
let cells = drain_insert_history(&mut rx);
|
||||
assert_eq!(cells.len(), 1, "expected one cooldown message");
|
||||
let rendered = lines_to_single_string(&cells[0]);
|
||||
assert!(
|
||||
rendered.contains("Workspace owner was already notified recently."),
|
||||
"expected cooldown message, got {rendered:?}"
|
||||
);
|
||||
assert!(
|
||||
!chat.notify_workspace_owner_in_flight,
|
||||
"notify-owner state should clear after cooldown"
|
||||
);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn notify_workspace_owner_error_adds_retry_message() {
|
||||
let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await;
|
||||
chat.start_notify_workspace_owner();
|
||||
|
||||
chat.finish_notify_workspace_owner(Err("backend failed".to_string()));
|
||||
|
||||
let cells = drain_insert_history(&mut rx);
|
||||
assert_eq!(cells.len(), 1, "expected one error message");
|
||||
let rendered = lines_to_single_string(&cells[0]);
|
||||
assert!(
|
||||
rendered.contains("Could not notify your workspace owner. Please try again."),
|
||||
"expected retry message, got {rendered:?}"
|
||||
);
|
||||
assert!(
|
||||
!chat.notify_workspace_owner_in_flight,
|
||||
"notify-owner state should clear after errors"
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user