Forge
csharpdeeb25a2
1using System.Text.Json;
2using CascadeIDE.Services;
3using Json.Schema;
4using Xunit;
5
6namespace CascadeIDE.Tests;
7
8/// <summary>Profile <c>cide-intent-catalog</c>: bundled catalog is structurally valid and loads with prod semantics.</summary>
9public sealed class IntentCatalogProfileSemanticsTests
10{
11 [Fact]
12 public void Bundled_catalog_matches_json_schema()
13 {
14 Assert.True(File.Exists(IntentCatalogProfileSupport.SchemaPath), IntentCatalogProfileSupport.SchemaPath);
15
16 var schema = JsonSchema.FromFile(IntentCatalogProfileSupport.SchemaPath);
17 var document = IntentCatalogProfileSupport.ToJsonNode(IntentCatalogProfileSupport.ReadSourceCatalogText());
18 var element = document.Deserialize<JsonElement>();
19
20 var result = schema.Evaluate(element, new EvaluationOptions { OutputFormat = OutputFormat.List });
21 Assert.True(result.IsValid, FormatSchemaErrors(result));
22 }
23
24 [Fact]
25 public void Bundled_catalog_loads_via_prod_loader()
26 {
27 IntentMelodyAliases.ResetForTests();
28 var snapshot = IntentMelodyAliases.GetCatalogSnapshot();
29
30 Assert.NotEmpty(snapshot.SlashRoutes);
31 Assert.True(snapshot.Roots.Count + snapshot.SlashRoutes.Count > 0);
32 }
33
34 [Fact]
35 public void Bundled_catalog_command_ids_are_registered_in_IdeCommands()
36 {
37 IntentMelodyAliases.ResetForTests();
38 var snapshot = IntentMelodyAliases.GetCatalogSnapshot();
39 var unknown = IntentCatalogProfileSupport.CollectCommandIds(snapshot)
40 .Where(id => !IntentCatalogProfileSupport.TryGetIdeCommandSummary(id, out _))
41 .OrderBy(id => id, StringComparer.Ordinal)
42 .ToList();
43
44 Assert.True(
45 unknown.Count == 0,
46 "command_id not in IdeCommands contract: " + string.Join(", ", unknown));
47 }
48
49 [Fact]
50 public void Source_catalog_declares_schema_directive()
51 {
52 using var reader = File.OpenText(IntentCatalogProfileSupport.SourceCatalogPath);
53 for (var i = 0; i < 8 && !reader.EndOfStream; i++)
54 {
55 var line = reader.ReadLine();
56 if (line is null)
57 break;
58
59 if (line.Contains("#:schema", StringComparison.OrdinalIgnoreCase))
60 return;
61 }
62
63 Assert.Fail("Missing #:schema directive in IntentMelody/intent-catalog.toml");
64 }
65
66 private static string FormatSchemaErrors(EvaluationResults result)
67 {
68 var lines = new List<string>();
69 WalkErrors(result, lines);
70 return lines.Count == 0 ? "JSON Schema validation failed." : string.Join(Environment.NewLine, lines);
71 }
72
73 private static void WalkErrors(EvaluationResults node, List<string> lines)
74 {
75 if (node.Errors is { Count: > 0 })
76 {
77 var location = string.IsNullOrWhiteSpace(node.EvaluationPath.ToString())
78 ? "$"
79 : node.EvaluationPath.ToString();
80 foreach (var (key, message) in node.Errors)
81 lines.Add($"{location}: {key} — {message}");
82 }
83
84 if (node.Details is null)
85 return;
86
87 foreach (var child in node.Details)
88 WalkErrors(child, lines);
89 }
90}
91
View only · write via MCP/CIDE