mirror of
https://github.com/GeWuYou/GFramework.git
synced 2026-04-02 20:09:00 +08:00
- 实现基于YAML的配置源文件和JSON Schema结构验证 - 提供运行时只读查询和Source Generator代码生成 - 添加VS Code插件实现配置浏览、编辑和轻量校验功能 - 支持开发期热重载和跨表引用校验 - 实现批量编辑和表单预览功能
180 lines
5.0 KiB
JavaScript
180 lines
5.0 KiB
JavaScript
const test = require("node:test");
|
|
const assert = require("node:assert/strict");
|
|
const {
|
|
applyFormUpdates,
|
|
applyScalarUpdates,
|
|
getEditableSchemaFields,
|
|
parseBatchArrayValue,
|
|
parseSchemaContent,
|
|
parseTopLevelYaml,
|
|
validateParsedConfig
|
|
} = require("../src/configValidation");
|
|
|
|
test("parseSchemaContent should capture scalar and array property metadata", () => {
|
|
const schema = parseSchemaContent(`
|
|
{
|
|
"type": "object",
|
|
"required": ["id", "name"],
|
|
"properties": {
|
|
"id": { "type": "integer" },
|
|
"name": { "type": "string" },
|
|
"dropRates": {
|
|
"type": "array",
|
|
"items": { "type": "integer" }
|
|
}
|
|
}
|
|
}
|
|
`);
|
|
|
|
assert.deepEqual(schema.required, ["id", "name"]);
|
|
assert.deepEqual(schema.properties, {
|
|
id: {type: "integer"},
|
|
name: {type: "string"},
|
|
dropRates: {type: "array", itemType: "integer"}
|
|
});
|
|
});
|
|
|
|
test("validateParsedConfig should report missing and unknown properties", () => {
|
|
const schema = parseSchemaContent(`
|
|
{
|
|
"type": "object",
|
|
"required": ["id", "name"],
|
|
"properties": {
|
|
"id": { "type": "integer" },
|
|
"name": { "type": "string" }
|
|
}
|
|
}
|
|
`);
|
|
const yaml = parseTopLevelYaml(`
|
|
id: 1
|
|
title: Slime
|
|
`);
|
|
|
|
const diagnostics = validateParsedConfig(schema, yaml);
|
|
|
|
assert.equal(diagnostics.length, 2);
|
|
assert.equal(diagnostics[0].severity, "error");
|
|
assert.match(diagnostics[0].message, /name/u);
|
|
assert.equal(diagnostics[1].severity, "error");
|
|
assert.match(diagnostics[1].message, /title/u);
|
|
});
|
|
|
|
test("validateParsedConfig should report array item type mismatches", () => {
|
|
const schema = parseSchemaContent(`
|
|
{
|
|
"type": "object",
|
|
"properties": {
|
|
"dropRates": {
|
|
"type": "array",
|
|
"items": { "type": "integer" }
|
|
}
|
|
}
|
|
}
|
|
`);
|
|
const yaml = parseTopLevelYaml(`
|
|
dropRates:
|
|
- 1
|
|
- potion
|
|
`);
|
|
|
|
const diagnostics = validateParsedConfig(schema, yaml);
|
|
|
|
assert.equal(diagnostics.length, 1);
|
|
assert.equal(diagnostics[0].severity, "error");
|
|
assert.match(diagnostics[0].message, /dropRates/u);
|
|
});
|
|
|
|
test("parseTopLevelYaml should classify nested mappings as object entries", () => {
|
|
const yaml = parseTopLevelYaml(`
|
|
reward:
|
|
gold: 10
|
|
name: Slime
|
|
`);
|
|
|
|
assert.equal(yaml.entries.get("reward").kind, "object");
|
|
assert.equal(yaml.entries.get("name").kind, "scalar");
|
|
});
|
|
|
|
test("applyScalarUpdates should update top-level scalars and append new keys", () => {
|
|
const updated = applyScalarUpdates(
|
|
[
|
|
"id: 1",
|
|
"name: Slime",
|
|
"dropRates:",
|
|
" - 1"
|
|
].join("\n"),
|
|
{
|
|
name: "Goblin",
|
|
hp: "25"
|
|
});
|
|
|
|
assert.match(updated, /^name: Goblin$/mu);
|
|
assert.match(updated, /^hp: 25$/mu);
|
|
assert.match(updated, /^ - 1$/mu);
|
|
});
|
|
|
|
test("applyFormUpdates should replace top-level scalar arrays and preserve unrelated content", () => {
|
|
const updated = applyFormUpdates(
|
|
[
|
|
"id: 1",
|
|
"name: Slime",
|
|
"dropItems:",
|
|
" - potion",
|
|
" - slime_gel",
|
|
"reward:",
|
|
" gold: 10"
|
|
].join("\n"),
|
|
{
|
|
scalars: {
|
|
name: "Goblin"
|
|
},
|
|
arrays: {
|
|
dropItems: ["bomb", "hi potion"]
|
|
}
|
|
});
|
|
|
|
assert.match(updated, /^name: Goblin$/mu);
|
|
assert.match(updated, /^dropItems:$/mu);
|
|
assert.match(updated, /^ - bomb$/mu);
|
|
assert.match(updated, /^ - hi potion$/mu);
|
|
assert.match(updated, /^reward:$/mu);
|
|
assert.match(updated, /^ gold: 10$/mu);
|
|
});
|
|
|
|
test("getEditableSchemaFields should expose only scalar and scalar-array properties", () => {
|
|
const schema = parseSchemaContent(`
|
|
{
|
|
"type": "object",
|
|
"required": ["id", "dropItems"],
|
|
"properties": {
|
|
"id": { "type": "integer" },
|
|
"name": { "type": "string" },
|
|
"reward": { "type": "object" },
|
|
"dropItems": {
|
|
"type": "array",
|
|
"items": { "type": "string" }
|
|
},
|
|
"waypoints": {
|
|
"type": "array",
|
|
"items": { "type": "object" }
|
|
}
|
|
}
|
|
}
|
|
`);
|
|
|
|
assert.deepEqual(getEditableSchemaFields(schema), [
|
|
{key: "dropItems", type: "array", itemType: "string", inputKind: "array", required: true},
|
|
{key: "id", type: "integer", inputKind: "scalar", required: true},
|
|
{key: "name", type: "string", inputKind: "scalar", required: false}
|
|
]);
|
|
});
|
|
|
|
test("parseBatchArrayValue should split comma-separated items and drop empty segments", () => {
|
|
assert.deepEqual(parseBatchArrayValue(" potion, hi potion , ,bomb "), [
|
|
"potion",
|
|
"hi potion",
|
|
"bomb"
|
|
]);
|
|
assert.deepEqual(parseBatchArrayValue(""), []);
|
|
});
|