Forge
csharp4405de34
1using System.Text.Json;
2using System.Text.Json.Nodes;
3using CascadeIDE.Features.Git.DataAcquisition;
4using CascadeIDE.Features.UiChrome;
5using CascadeIDE.Services;
6using CascadeIDE.Services.AgentContract;
7using Xunit;
8
9namespace CascadeIDE.Tests;
10
11[Collection("UiModeCatalog")]
12public sealed class AgentContractRunnerTests : IDisposable
13{
14 public AgentContractRunnerTests() =>
15 UiModeCatalog.ResetForTests();
16
17 public void Dispose() =>
18 UiModeCatalog.ResetForTests();
19
20 [Fact]
21 public void Get_ui_modes_diagnostics_matches_UiModeCatalog_payload()
22 {
23 UiModeCatalog.Initialize();
24 var expected = UiModeCatalog.GetDiagnosticsJson();
25 var actual = AgentContractRunner.GetContractJson(IdeCommands.GetUiModesDiagnostics);
26 Assert.Equal(expected, actual);
27 }
28
29 [Fact]
30 public void Get_supported_editor_languages_matches_EditorLanguageSupport_payload()
31 {
32 var expected = EditorLanguageSupport.GetJson();
33 var actual = AgentContractRunner.GetContractJson(IdeCommands.GetSupportedEditorLanguages);
34 Assert.Equal(expected, actual);
35 }
36
37 [Fact]
38 public void Get_ui_modes_diagnostics_normalized_paths_are_stable()
39 {
40 UiModeCatalog.Initialize();
41 var raw = AgentContractRunner.GetContractJson(IdeCommands.GetUiModesDiagnostics);
42 var normalized = NormalizeUiModesDiagnosticsPaths(raw);
43 using var doc = JsonDocument.Parse(normalized);
44 Assert.Equal("<BASE>", doc.RootElement.GetProperty("app_base_directory").GetString());
45 Assert.StartsWith("<BASE>", doc.RootElement.GetProperty("ui_modes_directory").GetString(), StringComparison.Ordinal);
46 Assert.StartsWith("<BASE>", doc.RootElement.GetProperty("index_toml_path").GetString(), StringComparison.Ordinal);
47 Assert.True(doc.RootElement.GetProperty("ui_mode_catalog_initialized").GetBoolean());
48 }
49
50 /// <summary>Как в ADR 0052: убрать машинно-зависимые префиксы для снапшотов.</summary>
51 internal static string NormalizeUiModesDiagnosticsPaths(string json)
52 {
53 var node = JsonNode.Parse(json)!;
54 var baseDir = node["app_base_directory"]?.GetValue<string>();
55 if (string.IsNullOrEmpty(baseDir))
56 return json;
57
58 var normalizedBase = baseDir.TrimEnd(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar);
59 node["app_base_directory"] = "<BASE>";
60
61 foreach (var key in new[] { "ui_modes_directory", "index_toml_path" })
62 {
63 if (node[key]?.GetValue<string>() is not { } p)
64 continue;
65 if (p.StartsWith(normalizedBase, StringComparison.OrdinalIgnoreCase))
66 {
67 var tail = p[normalizedBase.Length..].Replace('\\', '/');
68 node[key] = "<BASE>" + tail;
69 }
70 }
71
72 return node.ToJsonString(new JsonSerializerOptions { WriteIndented = false });
73 }
74
75 [Fact]
76 public async Task Git_status_uses_workspace_and_returns_json_shape()
77 {
78 var tmp = Directory.CreateTempSubdirectory("cascade_agent_contract_git_");
79 try
80 {
81 await RunGitAsync(tmp.FullName, "init");
82 File.WriteAllText(Path.Combine(tmp.FullName, "a.txt"), "x");
83 await RunGitAsync(tmp.FullName, "add", "a.txt");
84 await RunGitAsync(tmp.FullName, "-c", "user.email=t@t", "-c", "user.name=t", "commit", "-m", "init");
85
86 var json = AgentContractRunner.GetContractJson(
87 ["--workspace", tmp.FullName, IdeCommands.GitStatus]);
88 using var doc = JsonDocument.Parse(json);
89 Assert.True(doc.RootElement.TryGetProperty("success", out var ok));
90 Assert.True(ok.GetBoolean());
91 Assert.True(doc.RootElement.TryGetProperty("exit_code", out var code));
92 Assert.Equal(0, code.GetInt32());
93 Assert.True(doc.RootElement.TryGetProperty("output", out var output));
94 Assert.False(string.IsNullOrEmpty(output.GetString()));
95 }
96 finally
97 {
98 try
99 {
100 Directory.Delete(tmp.FullName, recursive: true);
101 }
102 catch
103 {
104 // best effort
105 }
106 }
107 }
108
109 private static async Task RunGitAsync(string workingDirectory, params string[] args)
110 {
111 var git = new GitCommandRunner();
112 var (success, exitCode, _) = await git.RunAsync(args, workingDirectory).ConfigureAwait(false);
113 Assert.True(success);
114 Assert.Equal(0, exitCode);
115 }
116}
117
View only · write via MCP/CIDE