multi_workspace_tests.rs

  1use super::*;
  2use feature_flags::FeatureFlagAppExt;
  3use fs::FakeFs;
  4use gpui::TestAppContext;
  5use project::DisableAiSettings;
  6use settings::SettingsStore;
  7
  8fn init_test(cx: &mut TestAppContext) {
  9    cx.update(|cx| {
 10        let settings_store = SettingsStore::test(cx);
 11        cx.set_global(settings_store);
 12        theme_settings::init(theme::LoadThemes::JustBase, cx);
 13        DisableAiSettings::register(cx);
 14        cx.update_flags(false, vec!["agent-v2".into()]);
 15    });
 16}
 17
 18#[gpui::test]
 19async fn test_sidebar_disabled_when_disable_ai_is_enabled(cx: &mut TestAppContext) {
 20    init_test(cx);
 21    let fs = FakeFs::new(cx.executor());
 22    let project = Project::test(fs, [], cx).await;
 23
 24    let (multi_workspace, cx) =
 25        cx.add_window_view(|window, cx| MultiWorkspace::test_new(project, window, cx));
 26
 27    multi_workspace.read_with(cx, |mw, cx| {
 28        assert!(mw.multi_workspace_enabled(cx));
 29    });
 30
 31    multi_workspace.update_in(cx, |mw, _window, cx| {
 32        mw.open_sidebar(cx);
 33        assert!(mw.sidebar_open());
 34    });
 35
 36    cx.update(|_window, cx| {
 37        DisableAiSettings::override_global(DisableAiSettings { disable_ai: true }, cx);
 38    });
 39    cx.run_until_parked();
 40
 41    multi_workspace.read_with(cx, |mw, cx| {
 42        assert!(
 43            !mw.sidebar_open(),
 44            "Sidebar should be closed when disable_ai is true"
 45        );
 46        assert!(
 47            !mw.multi_workspace_enabled(cx),
 48            "Multi-workspace should be disabled when disable_ai is true"
 49        );
 50    });
 51
 52    multi_workspace.update_in(cx, |mw, window, cx| {
 53        mw.toggle_sidebar(window, cx);
 54    });
 55    multi_workspace.read_with(cx, |mw, _cx| {
 56        assert!(
 57            !mw.sidebar_open(),
 58            "Sidebar should remain closed when toggled with disable_ai true"
 59        );
 60    });
 61
 62    cx.update(|_window, cx| {
 63        DisableAiSettings::override_global(DisableAiSettings { disable_ai: false }, cx);
 64    });
 65    cx.run_until_parked();
 66
 67    multi_workspace.read_with(cx, |mw, cx| {
 68        assert!(
 69            mw.multi_workspace_enabled(cx),
 70            "Multi-workspace should be enabled after re-enabling AI"
 71        );
 72        assert!(
 73            !mw.sidebar_open(),
 74            "Sidebar should still be closed after re-enabling AI (not auto-opened)"
 75        );
 76    });
 77
 78    multi_workspace.update_in(cx, |mw, window, cx| {
 79        mw.toggle_sidebar(window, cx);
 80    });
 81    multi_workspace.read_with(cx, |mw, _cx| {
 82        assert!(
 83            mw.sidebar_open(),
 84            "Sidebar should open when toggled after re-enabling AI"
 85        );
 86    });
 87}
 88
 89#[gpui::test]
 90async fn test_replace(cx: &mut TestAppContext) {
 91    init_test(cx);
 92    let fs = FakeFs::new(cx.executor());
 93    let project_a = Project::test(fs.clone(), [], cx).await;
 94    let project_b = Project::test(fs.clone(), [], cx).await;
 95    let project_c = Project::test(fs.clone(), [], cx).await;
 96    let project_d = Project::test(fs.clone(), [], cx).await;
 97
 98    let (multi_workspace, cx) =
 99        cx.add_window_view(|window, cx| MultiWorkspace::test_new(project_a.clone(), window, cx));
100
101    let workspace_a_id = multi_workspace.read_with(cx, |mw, _cx| {
102        mw.workspaces()
103            .next()
104            .expect("workspace should exist")
105            .entity_id()
106    });
107
108    // Replace the only workspace (single-workspace case).
109    let workspace_b = multi_workspace.update_in(cx, |mw, window, cx| {
110        let workspace = cx.new(|cx| Workspace::test_new(project_b.clone(), window, cx));
111        mw.replace(workspace.clone(), window, cx);
112        workspace
113    });
114
115    multi_workspace.read_with(cx, |mw, _cx| {
116        assert_eq!(mw.len(), 1);
117        assert_eq!(
118            mw.workspaces()
119                .next()
120                .expect("workspace should exist")
121                .entity_id(),
122            workspace_b.entity_id(),
123            "slot should now be project_b"
124        );
125        assert_ne!(
126            mw.workspaces()
127                .next()
128                .expect("workspace should exist")
129                .entity_id(),
130            workspace_a_id,
131            "project_a should be gone"
132        );
133    });
134
135    // Add project_c as a second workspace, then replace it with project_d.
136    let workspace_c = multi_workspace.update_in(cx, |mw, window, cx| {
137        mw.test_add_workspace(project_c.clone(), window, cx)
138    });
139
140    multi_workspace.read_with(cx, |mw, _cx| {
141        assert_eq!(mw.len(), 2);
142        assert_eq!(
143            mw.workspaces()
144                .position(|workspace| workspace == mw.active_workspace()),
145            Some(1)
146        );
147    });
148
149    let workspace_d = multi_workspace.update_in(cx, |mw, window, cx| {
150        let workspace = cx.new(|cx| Workspace::test_new(project_d.clone(), window, cx));
151        mw.replace(workspace.clone(), window, cx);
152        workspace
153    });
154
155    multi_workspace.read_with(cx, |mw, _cx| {
156        assert_eq!(mw.len(), 2, "should still have 2 workspaces");
157        assert_eq!(
158            mw.workspaces()
159                .position(|workspace| workspace == mw.active_workspace()),
160            Some(1)
161        );
162        assert_eq!(
163            mw.workspaces()
164                .nth(1)
165                .expect("no workspace at index 1")
166                .entity_id(),
167            workspace_d.entity_id(),
168            "active slot should now be project_d"
169        );
170        assert_ne!(
171            mw.workspaces()
172                .nth(1)
173                .expect("no workspace at index 1")
174                .entity_id(),
175            workspace_c.entity_id(),
176            "project_c should be gone"
177        );
178    });
179
180    // Replace with workspace_b which is already in the list — should just switch.
181    multi_workspace.update_in(cx, |mw, window, cx| {
182        mw.replace(workspace_b.clone(), window, cx);
183    });
184
185    multi_workspace.read_with(cx, |mw, _cx| {
186        assert_eq!(mw.len(), 2, "no workspace should be added or removed");
187        assert_eq!(
188            mw.workspaces()
189                .position(|workspace| workspace == mw.active_workspace()),
190            Some(0),
191            "should have switched to workspace_b"
192        );
193    });
194}