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| mw.workspaces()[0].entity_id());
102
103 // Replace the only workspace (single-workspace case).
104 let workspace_b = multi_workspace.update_in(cx, |mw, window, cx| {
105 let workspace = cx.new(|cx| Workspace::test_new(project_b.clone(), window, cx));
106 mw.replace(workspace.clone(), &*window, cx);
107 workspace
108 });
109
110 multi_workspace.read_with(cx, |mw, _cx| {
111 assert_eq!(mw.workspaces().len(), 1);
112 assert_eq!(
113 mw.workspaces()[0].entity_id(),
114 workspace_b.entity_id(),
115 "slot should now be project_b"
116 );
117 assert_ne!(
118 mw.workspaces()[0].entity_id(),
119 workspace_a_id,
120 "project_a should be gone"
121 );
122 });
123
124 // Add project_c as a second workspace, then replace it with project_d.
125 let workspace_c = multi_workspace.update_in(cx, |mw, window, cx| {
126 mw.test_add_workspace(project_c.clone(), window, cx)
127 });
128
129 multi_workspace.read_with(cx, |mw, _cx| {
130 assert_eq!(mw.workspaces().len(), 2);
131 assert_eq!(mw.active_workspace_index(), 1);
132 });
133
134 let workspace_d = multi_workspace.update_in(cx, |mw, window, cx| {
135 let workspace = cx.new(|cx| Workspace::test_new(project_d.clone(), window, cx));
136 mw.replace(workspace.clone(), &*window, cx);
137 workspace
138 });
139
140 multi_workspace.read_with(cx, |mw, _cx| {
141 assert_eq!(mw.workspaces().len(), 2, "should still have 2 workspaces");
142 assert_eq!(mw.active_workspace_index(), 1);
143 assert_eq!(
144 mw.workspaces()[1].entity_id(),
145 workspace_d.entity_id(),
146 "active slot should now be project_d"
147 );
148 assert_ne!(
149 mw.workspaces()[1].entity_id(),
150 workspace_c.entity_id(),
151 "project_c should be gone"
152 );
153 });
154
155 // Replace with workspace_b which is already in the list — should just switch.
156 multi_workspace.update_in(cx, |mw, window, cx| {
157 mw.replace(workspace_b.clone(), &*window, cx);
158 });
159
160 multi_workspace.read_with(cx, |mw, _cx| {
161 assert_eq!(
162 mw.workspaces().len(),
163 2,
164 "no workspace should be added or removed"
165 );
166 assert_eq!(
167 mw.active_workspace_index(),
168 0,
169 "should have switched to workspace_b"
170 );
171 });
172}