Forge
csharpdeeb25a2
1using CascadeIDE.Cockpit;
2using CascadeIDE.Features.UiChrome;
3using Xunit;
4
5namespace CascadeIDE.Tests;
6
7[Collection("UiModeCatalog")]
8public sealed class UiModeCatalogTests : IDisposable
9{
10 public UiModeCatalogTests() =>
11 UiModeCatalog.ResetForTests();
12
13 public void Dispose() =>
14 UiModeCatalog.ResetForTests();
15
16 [Fact]
17 public void Inherits_copies_debug_family_and_layout()
18 {
19 var dir = Path.Combine(Path.GetTempPath(), "uimodes_" + Guid.NewGuid());
20 Directory.CreateDirectory(dir);
21 File.WriteAllText(
22 Path.Combine(dir, "index.toml"),
23 """
24 [bundle]
25 schema_version = 1
26 modes = [ "Focus", "Balanced", "Power", "AgentChat", "Debug", "MySuperDebug" ]
27 """);
28 File.WriteAllText(
29 Path.Combine(dir, "MySuperDebug.toml"),
30 """
31 [meta]
32 inherits = "Debug"
33 """);
34
35 UiModeCatalog.Initialize(dir);
36
37 Assert.Equal(UiModeFamily.Debug, UiModeCatalog.GetFamily("MySuperDebug"));
38 var dbg = UiModeCatalog.GetSpec("Debug");
39 var mine = UiModeCatalog.GetSpec("MySuperDebug");
40 Assert.Equal(dbg.PfdRegionExpanded, mine.PfdRegionExpanded);
41 Assert.Equal(dbg.EditorGroupCount, mine.EditorGroupCount);
42 Assert.Equal(
43 UiModeCatalog.GetMfdRegionExpandedWidthPixels("Debug"),
44 UiModeCatalog.GetMfdRegionExpandedWidthPixels("MySuperDebug"));
45 Assert.False(UiModeCatalog.GetShowTaskBar("Debug"));
46 Assert.False(UiModeCatalog.GetShowTaskBar("MySuperDebug"));
47 Assert.Equal(UiModeCatalog.GetCapabilities("Debug"), UiModeCatalog.GetCapabilities("MySuperDebug"));
48 }
49
50 [Fact]
51 public void Inherits_uses_parent_mfd_width_when_child_omits_mfd_region_expanded_width_pixels()
52 {
53 var dir = Path.Combine(Path.GetTempPath(), "uimodes_" + Guid.NewGuid());
54 Directory.CreateDirectory(dir);
55 File.WriteAllText(
56 Path.Combine(dir, "index.toml"),
57 """
58 [bundle]
59 schema_version = 1
60 modes = [ "Balanced", "DerivedBalanced" ]
61 """);
62 File.WriteAllText(
63 Path.Combine(dir, "Balanced.toml"),
64 """
65 [layout]
66 mfd_region_expanded_width_pixels = 555
67 """);
68 File.WriteAllText(
69 Path.Combine(dir, "DerivedBalanced.toml"),
70 """
71 [meta]
72 inherits = "Balanced"
73 """);
74
75 UiModeCatalog.Initialize(dir);
76
77 Assert.Equal(555, UiModeCatalog.GetMfdRegionExpandedWidthPixels("Balanced"));
78 Assert.Equal(555, UiModeCatalog.GetMfdRegionExpandedWidthPixels("DerivedBalanced"));
79 }
80
81 [Fact]
82 public void Show_task_cockpit_defaults_false_for_debug_family_without_toml()
83 {
84 var dir = Path.Combine(Path.GetTempPath(), "uimodes_" + Guid.NewGuid());
85 Directory.CreateDirectory(dir);
86 File.WriteAllText(
87 Path.Combine(dir, "index.toml"),
88 """
89 [bundle]
90 schema_version = 1
91 modes = [ "Debug" ]
92 """);
93
94 UiModeCatalog.Initialize(dir);
95
96 Assert.False(UiModeCatalog.GetShowTaskBar("Debug"));
97 }
98
99 [Fact]
100 public void Show_task_cockpit_toml_can_override_true()
101 {
102 var dir = Path.Combine(Path.GetTempPath(), "uimodes_" + Guid.NewGuid());
103 Directory.CreateDirectory(dir);
104 File.WriteAllText(
105 Path.Combine(dir, "index.toml"),
106 """
107 [bundle]
108 schema_version = 1
109 modes = [ "Debug" ]
110 """);
111 File.WriteAllText(
112 Path.Combine(dir, "Debug.toml"),
113 """
114 [layout]
115 active_task_strip = true
116 """);
117
118 UiModeCatalog.Initialize(dir);
119
120 Assert.True(UiModeCatalog.GetShowTaskBar("Debug"));
121 }
122
123 [Fact]
124 public void Normalize_preserves_canonical_id_from_index()
125 {
126 var dir = Path.Combine(Path.GetTempPath(), "uimodes_" + Guid.NewGuid());
127 Directory.CreateDirectory(dir);
128 File.WriteAllText(
129 Path.Combine(dir, "index.toml"),
130 """
131 [bundle]
132 schema_version = 1
133 modes = [ "Focus", "MySuperDebug" ]
134 """);
135 File.WriteAllText(
136 Path.Combine(dir, "MySuperDebug.toml"),
137 """
138 [meta]
139 inherits = "Focus"
140 """);
141
142 UiModeCatalog.Initialize(dir);
143
144 Assert.Equal("MySuperDebug", UiModeCatalog.NormalizeUiMode("mysuperdebug"));
145 }
146
147 [Fact]
148 public void Capabilities_defaults_per_family_and_power_column_span()
149 {
150 var dir = Path.Combine(Path.GetTempPath(), "uimodes_" + Guid.NewGuid());
151 Directory.CreateDirectory(dir);
152 File.WriteAllText(
153 Path.Combine(dir, "index.toml"),
154 """
155 [bundle]
156 schema_version = 1
157 modes = [ "Balanced", "Debug", "Power", "Focus", "AgentChat", "Flight" ]
158 """);
159
160 UiModeCatalog.Initialize(dir);
161
162 var balanced = UiModeCatalog.GetCapabilities("Balanced");
163 Assert.True(balanced.QuickActions);
164 Assert.True(balanced.AgentOperationsPanel);
165 Assert.False(balanced.HypothesesTab);
166 Assert.True(balanced.RiskSummaryCard);
167
168 var debug = UiModeCatalog.GetCapabilities("Debug");
169 Assert.False(debug.QuickActions);
170 Assert.False(debug.HypothesesTab);
171 Assert.True(debug.RiskSummaryCard);
172
173 var flight = UiModeCatalog.GetCapabilities("Flight");
174 Assert.True(flight.HypothesesTab);
175
176 var power = UiModeCatalog.GetCapabilities("Power");
177 Assert.True(power.AgentTrace);
178 Assert.True(power.AutonomousAgentTelemetry);
179 Assert.Equal(3, power.IdeHealthMainColumnSpan);
180
181 Assert.False(UiModeCatalog.GetCapabilities("Focus").RiskSummaryCard);
182 Assert.False(UiModeCatalog.GetCapabilities("AgentChat").ResultSummaryCard);
183 }
184
185 [Fact]
186 public void Flight_inherits_balanced_spec_and_uses_flight_family()
187 {
188 var dir = Path.Combine(Path.GetTempPath(), "uimodes_" + Guid.NewGuid());
189 Directory.CreateDirectory(dir);
190 File.WriteAllText(
191 Path.Combine(dir, "index.toml"),
192 """
193 [bundle]
194 schema_version = 1
195 modes = [ "Balanced", "Flight" ]
196 """);
197 File.WriteAllText(
198 Path.Combine(dir, "Flight.toml"),
199 """
200 [meta]
201 inherits = "Balanced"
202 family = "Flight"
203 main_window_title = "CascadeIDE — Flight (test)"
204 """);
205
206 UiModeCatalog.Initialize(dir);
207
208 Assert.Equal(UiModeFamily.Flight, UiModeCatalog.GetFamily("Flight"));
209 Assert.Equal(UiModeCatalog.GetSpec("Balanced"), UiModeCatalog.GetSpec("Flight"));
210 Assert.Equal(UiModeCatalog.GetCapabilities("Balanced"), UiModeCatalog.GetCapabilities("Flight"));
211 Assert.Equal("CascadeIDE — Flight (test)", UiModeCatalog.GetWindowTitleOverride("Flight"));
212 }
213
214 [Fact]
215 public void Capabilities_toml_overrides_and_window_title()
216 {
217 var dir = Path.Combine(Path.GetTempPath(), "uimodes_" + Guid.NewGuid());
218 Directory.CreateDirectory(dir);
219 File.WriteAllText(
220 Path.Combine(dir, "index.toml"),
221 """
222 [bundle]
223 schema_version = 1
224 modes = [ "Debug" ]
225 """);
226 File.WriteAllText(
227 Path.Combine(dir, "Debug.toml"),
228 """
229 [capabilities]
230 hypotheses_tab = false
231 ide_health_main_column_span = 4
232
233 [meta]
234 main_window_title = "IDE — Debug (custom)"
235 """);
236
237 UiModeCatalog.Initialize(dir);
238
239 var caps = UiModeCatalog.GetCapabilities("Debug");
240 Assert.False(caps.HypothesesTab);
241 Assert.Equal(4, caps.IdeHealthMainColumnSpan);
242
243 Assert.Equal("IDE — Debug (custom)", UiModeCatalog.GetWindowTitleOverride("Debug"));
244 }
245
246 [Fact]
247 public void Editor_family_minimal_chrome_and_layout()
248 {
249 var dir = Path.Combine(Path.GetTempPath(), "uimodes_" + Guid.NewGuid());
250 Directory.CreateDirectory(dir);
251 File.WriteAllText(
252 Path.Combine(dir, "index.toml"),
253 """
254 [bundle]
255 schema_version = 1
256 modes = [ "Editor" ]
257 """);
258 File.WriteAllText(
259 Path.Combine(dir, "Editor.toml"),
260 """
261 [meta]
262 inherits = "Flight"
263 family = "Editor"
264
265 [layout]
266 instrumentation_dock_visible = false
267 active_task_strip = false
268
269 [capabilities]
270 quick_actions = false
271 agent_operations_panel = false
272 agent_trace = false
273 autonomous_agent_telemetry = false
274 ide_health_on_terminal_tab = false
275 ide_health_main_column_span = 5
276 instrumentation_tabs = false
277 hypotheses_tab = false
278 risk_summary_card = false
279 result_summary_card = false
280 ide_health_strip = false
281 ide_health_surface = "bottom_strip"
282 problems_panel = false
283 eicas_alerts_bar = false
284 """);
285
286 UiModeCatalog.Initialize(dir);
287
288 Assert.Equal(UiModeFamily.Editor, UiModeCatalog.GetFamily("Editor"));
289 Assert.False(UiModeCatalog.GetShowTaskBar("Editor"));
290
291 var spec = UiModeCatalog.GetSpec("Editor");
292 Assert.True(spec.PfdRegionExpanded);
293 Assert.True(spec.MfdRegionExpanded);
294 Assert.False(spec.InstrumentationDockVisible);
295
296 var caps = UiModeCatalog.GetCapabilities("Editor");
297 Assert.False(caps.IdeHealthStripVisible);
298 Assert.False(caps.ProblemsPanelVisible);
299 }
300
301 [Fact]
302 public void Telemetry_surface_toml_sets_dedicated_page()
303 {
304 var dir = Path.Combine(Path.GetTempPath(), "uimodes_" + Guid.NewGuid());
305 Directory.CreateDirectory(dir);
306 File.WriteAllText(
307 Path.Combine(dir, "index.toml"),
308 """
309 [bundle]
310 schema_version = 1
311 modes = [ "Balanced" ]
312 """);
313 File.WriteAllText(
314 Path.Combine(dir, "Balanced.toml"),
315 """
316 [capabilities]
317 ide_health_surface = "dedicated_page"
318 """);
319
320 UiModeCatalog.Initialize(dir);
321
322 var caps = UiModeCatalog.GetCapabilities("Balanced");
323 Assert.Equal(IdeHealthUiSurface.DedicatedPage, caps.IdeHealthSurface);
324 Assert.Equal(ContentRepresentation.Page, caps.IdeHealthContentRepresentation);
325 }
326
327 [Fact]
328 public void Workspace_health_ui_surface_maps_to_content_representation_axis()
329 {
330 Assert.Equal(ContentRepresentation.Strip, IdeHealthUiSurface.BottomStrip.ToContentRepresentation());
331 Assert.Equal(ContentRepresentation.Page, IdeHealthUiSurface.DedicatedPage.ToContentRepresentation());
332 }
333
334 [Fact]
335 public void Empty_override_directory_loads_embedded_uimodes_bundle()
336 {
337 var dir = Path.Combine(Path.GetTempPath(), "uimodes_empty_" + Guid.NewGuid());
338 Directory.CreateDirectory(dir);
339
340 UiModeCatalog.Initialize(dir);
341
342 Assert.Equal(UiModesBundleSource.TomlBundle, UiModeCatalog.ActiveBundleSource);
343 Assert.Equal(new[] { "Flight" }, UiModeCatalog.OrderedModeIds.ToArray());
344 }
345
346 [Fact]
347 public void Invalid_index_toml_falls_back_to_builtin_registry()
348 {
349 var dir = Path.Combine(Path.GetTempPath(), "uimodes_bad_index_" + Guid.NewGuid());
350 Directory.CreateDirectory(dir);
351 File.WriteAllText(Path.Combine(dir, "index.toml"), "not valid toml {{{");
352
353 UiModeCatalog.Initialize(dir);
354
355 Assert.Equal(UiModesBundleSource.BuiltinRegistry, UiModeCatalog.ActiveBundleSource);
356 Assert.Equal(UiModeLayoutRegistry.OrderedModeIds, UiModeCatalog.OrderedModeIds);
357 Assert.Equal("Flight", UiModeCatalog.NormalizeUiMode("nope"));
358 }
359}
360
View only · write via MCP/CIDE