Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 38 additions & 4 deletions crates/openshell-tui/src/app.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1216,11 +1216,16 @@ impl App {

pub fn cycle_workspace(&mut self) {
if self.all_workspaces {
self.all_workspaces = false;
self.current_workspace = "default".to_string();
// Leaving "all" scope: return to the first known named workspace.
// The workspace list is server-provided and membership-scoped, so
// it is not guaranteed to contain (or start with) "default"; only
// enter named scope when at least one workspace is known.
if let Some(first) = self.workspace_names.first() {
self.all_workspaces = false;
self.current_workspace = first.clone();
}
} else if self.workspace_names.is_empty() {
self.all_workspaces = true;
self.current_workspace = "default".to_string();
} else {
let current_idx = self
.workspace_names
Expand All @@ -1232,7 +1237,6 @@ impl App {
}
_ => {
self.all_workspaces = true;
self.current_workspace = "default".to_string();
}
}
}
Expand Down Expand Up @@ -4112,6 +4116,36 @@ mod tests {
assert_eq!(app.current_workspace, "default");
}

#[tokio::test]
async fn cycle_workspace_without_default_stays_on_real_workspaces() {
// The workspace list is server-provided and membership-scoped, so a
// non-admin principal may have no "default" workspace visible.
let mut app = test_app();
app.workspace_names = vec!["team-a".to_string(), "team-b".to_string()];
app.current_workspace = "team-a".to_string();
app.all_workspaces = false;

// Collect every named-scope selection across several full cycles. Each
// named scope must be a workspace that actually exists in the list;
// the cursor must never land on a phantom "default".
let mut named_scopes = Vec::new();
for _ in 0..8 {
if !app.all_workspaces {
assert!(
app.workspace_names.contains(&app.current_workspace),
"cycled to '{}', which is not a known workspace",
app.current_workspace
);
named_scopes.push(app.current_workspace.clone());
}
app.cycle_workspace();
}

// Both real workspaces must be reachable by repeated cycling.
assert!(named_scopes.iter().any(|w| w == "team-a"));
assert!(named_scopes.iter().any(|w| w == "team-b"));
}

// -- selected_sandbox_workspace ----------------------------------------

#[test]
Expand Down
Loading