mirror of
https://github.com/GeWuYou/GFramework.git
synced 2026-05-07 00:39:00 +08:00
- 实现 parseSchemaContent 函数解析对象和数组枚举元数据 - 添加 validateParsedConfig 验证对象值是否在枚举声明范围内 - 支持数组枚举候选项的顺序敏感比较 - 优化诊断信息避免父对象枚举不匹配的重复报告 - 添加测试用例验证枚举对象和数组的解析与验证功能 - 实现可编辑字段收集功能支持批量编辑器更新 - 添加 YAML 解析和注释提取功能用于表单预览 - 实现配置验证诊断生成功能支持本地化消息 - 添加格式化和规范化函数支持不同数据类型的处理
152 lines
5.5 KiB
C#
152 lines
5.5 KiB
C#
using System.IO;
|
|
using Microsoft.CodeAnalysis;
|
|
|
|
namespace GFramework.SourceGenerators.Tests.Config;
|
|
|
|
/// <summary>
|
|
/// 验证 schema 配置生成器对对象 / 数组 <c>enum</c> 文档输出的快照行为。
|
|
/// </summary>
|
|
[TestFixture]
|
|
public class SchemaConfigGeneratorEnumTests
|
|
{
|
|
/// <summary>
|
|
/// 验证对象 <c>enum</c> 文档输出与快照保持一致。
|
|
/// </summary>
|
|
[Test]
|
|
public async Task Snapshot_Should_Preserve_Object_Enum_Documentation()
|
|
{
|
|
const string source = """
|
|
namespace TestApp
|
|
{
|
|
public sealed class Dummy
|
|
{
|
|
}
|
|
}
|
|
""";
|
|
|
|
const string schema = """
|
|
{
|
|
"type": "object",
|
|
"required": ["id", "reward"],
|
|
"properties": {
|
|
"id": { "type": "integer" },
|
|
"reward": {
|
|
"type": "object",
|
|
"required": ["gold", "itemId"],
|
|
"properties": {
|
|
"gold": { "type": "integer" },
|
|
"itemId": { "type": "string" }
|
|
},
|
|
"enum": [
|
|
{ "gold": 10, "itemId": "potion" },
|
|
{ "gold": 50, "itemId": "gem" }
|
|
]
|
|
}
|
|
}
|
|
}
|
|
""";
|
|
|
|
var result = SchemaGeneratorTestDriver.Run(
|
|
source,
|
|
("monster.schema.json", schema));
|
|
|
|
Assert.That(result.Results.Single().Diagnostics, Is.Empty);
|
|
await AssertSnapshotAsync(result, "MonsterConfig.ObjectEnum.g.txt");
|
|
}
|
|
|
|
/// <summary>
|
|
/// 验证数组项 <c>enum</c> 文档回退输出与快照保持一致。
|
|
/// </summary>
|
|
[Test]
|
|
public async Task Snapshot_Should_Preserve_Array_Item_Enum_Documentation_Fallback()
|
|
{
|
|
const string source = """
|
|
namespace TestApp
|
|
{
|
|
public sealed class Dummy
|
|
{
|
|
}
|
|
}
|
|
""";
|
|
|
|
const string schema = """
|
|
{
|
|
"type": "object",
|
|
"required": ["id", "dropItemIds"],
|
|
"properties": {
|
|
"id": { "type": "integer" },
|
|
"dropItemIds": {
|
|
"type": "array",
|
|
"items": { "type": "string", "enum": ["fire", "ice", "earth"] }
|
|
}
|
|
}
|
|
}
|
|
""";
|
|
|
|
var result = SchemaGeneratorTestDriver.Run(
|
|
source,
|
|
("monster.schema.json", schema));
|
|
|
|
Assert.That(result.Results.Single().Diagnostics, Is.Empty);
|
|
await AssertSnapshotAsync(result, "MonsterConfig.ArrayItemEnum.g.txt");
|
|
}
|
|
|
|
/// <summary>
|
|
/// 对单个生成文件执行快照断言。
|
|
/// </summary>
|
|
/// <param name="result">生成器运行结果。</param>
|
|
/// <param name="snapshotFileName">快照文件名。</param>
|
|
private static async Task AssertSnapshotAsync(
|
|
GeneratorDriverRunResult result,
|
|
string snapshotFileName)
|
|
{
|
|
var generatedSources = result.Results
|
|
.Single()
|
|
.GeneratedSources
|
|
.ToDictionary(
|
|
static sourceResult => sourceResult.HintName,
|
|
static sourceResult => sourceResult.SourceText.ToString(),
|
|
StringComparer.Ordinal);
|
|
|
|
if (!generatedSources.TryGetValue("MonsterConfig.g.cs", out var actual))
|
|
{
|
|
Assert.Fail("Generated source 'MonsterConfig.g.cs' was not found.");
|
|
return;
|
|
}
|
|
|
|
var snapshotFolder = Path.Combine(
|
|
TestContext.CurrentContext.TestDirectory,
|
|
"..",
|
|
"..",
|
|
"..",
|
|
"Config",
|
|
"snapshots",
|
|
"SchemaConfigGeneratorEnum");
|
|
snapshotFolder = Path.GetFullPath(snapshotFolder);
|
|
|
|
var path = Path.Combine(snapshotFolder, snapshotFileName);
|
|
if (!File.Exists(path))
|
|
{
|
|
Directory.CreateDirectory(snapshotFolder);
|
|
await File.WriteAllTextAsync(path, actual);
|
|
Assert.Fail($"Snapshot not found. Generated new snapshot at:\n{path}");
|
|
}
|
|
|
|
var expected = await File.ReadAllTextAsync(path);
|
|
Assert.That(
|
|
Normalize(expected),
|
|
Is.EqualTo(Normalize(actual)),
|
|
$"Snapshot mismatch: MonsterConfig.g.cs ({snapshotFileName})");
|
|
}
|
|
|
|
/// <summary>
|
|
/// 标准化快照文本以避免平台换行差异。
|
|
/// </summary>
|
|
/// <param name="text">原始文本。</param>
|
|
/// <returns>标准化后的文本。</returns>
|
|
private static string Normalize(string text)
|
|
{
|
|
return text.Replace("\r\n", "\n", StringComparison.Ordinal).Trim();
|
|
}
|
|
}
|