feat: V1.1 - 写入点展示修复

This commit is contained in:
2026-08-03 13:40:40 +08:00
parent 69d581f034
commit 875c0f3ccb
5 changed files with 490 additions and 33 deletions

View File

@@ -362,12 +362,127 @@ class ReportBuilderTest {
report.getKeyChanges().add(key);
String md = new ReportBuilder("[序列化结构变更]").toMarkdown(report);
assertTrue(md.contains("- Key --> `req.getKey()` <font color=\"comment\">key 无法解析)</font>"));
assertTrue(md.contains("- Key --> `req.getKey()` <font color=\"comment\">key 无法解析,建议 manual_mappings 补充</font>"));
assertTrue(md.contains("> **位置**: ClockInXxxService#export:128"));
assertTrue(md.contains("> **类型**: List<ClockInExportVo>"));
assertFalse(md.contains("`unknown-key`"));
}
@Test
void writePointAddedMqShowsFriendlyCopyAndWholeSkeletonGreen() {
String skeleton = "{\"objectId\":\"\",\"content\":\"\",\"type\":0,\"pushStatus\":0,"
+ "\"tenantId\":\"\",\"deleteMark\":0,\"executeTime\":0}";
CheckReport report = baseReport();
SchemaChange added = new SchemaChange(ChangeType.WRITE_POINT_ADDED);
added.setMessage("新增 MQ 投递点value 类型: DutyImNotice");
added.setKeyPattern("duty_im_notice_topic");
report.getChanges().add(added);
KeyStructureChange key = new KeyStructureChange();
key.setKeyPattern("duty_im_notice_topic");
key.setChannel("ROCKETMQ");
key.setWriteLocation("DutyDelayQueueImNoticeService#addMq:43");
key.setValueType("DutyImNotice");
key.setOldSkeletonJson("");
key.setNewSkeletonJson(skeleton);
key.getFieldDetails().add(added);
report.getKeyChanges().add(key);
String md = new ReportBuilder("【序列化结构变更】").toMarkdown(report);
assertTrue(md.contains("- Topic --> `duty_im_notice_topic`"), md);
assertTrue(md.contains("> **通道**: RocketMQ"), md);
assertTrue(md.contains("> **变更类型**: 新增写入点"), md);
assertTrue(md.contains("> **新增投递,消息体结构为:**"), md);
assertTrue(md.contains("<font color=\"info\">" + skeleton + "</font>"), md);
assertFalse(md.contains("value 新增为"), md);
String console = new ReportBuilder("【序列化结构变更】").toConsole(report);
assertTrue(console.contains("**新增 MQ 投递点**: value 类型: DutyImNotice"), console);
}
@Test
void writePointAddedRedisShowsFriendlyCopyAndWholeSkeletonGreen() {
String skeleton = "{\"taskId\":\"\",\"status\":\"\"}";
CheckReport report = baseReport();
SchemaChange added = new SchemaChange(ChangeType.WRITE_POINT_ADDED);
added.setMessage("新增缓存写入点value 类型: MigrationCurrentVo");
KeyStructureChange key = new KeyStructureChange();
key.setKeyPattern("saas:period-config:migration:current");
key.setWriteLocation("SaasPeriodConfigMigrationRedisSupport#putCurrent:41");
key.setValueType("MigrationCurrentVo");
key.setOldSkeletonJson("");
key.setNewSkeletonJson(skeleton);
key.getFieldDetails().add(added);
report.getKeyChanges().add(key);
String md = new ReportBuilder("[序列化结构变更]").toMarkdown(report);
assertTrue(md.contains("> **变更类型**: 新增写入点"), md);
assertTrue(md.contains("> **首次写入该 Keyvalue 结构为:**"), md);
assertTrue(md.contains("<font color=\"info\">" + skeleton + "</font>"), md);
assertFalse(md.contains("value 新增为"), md);
}
@Test
void writePointRemovedHighlightsWholeOldSkeletonOrange() {
String skeleton = "{\"objectId\":\"\",\"content\":\"\"}";
CheckReport report = baseReport();
SchemaChange removed = new SchemaChange(ChangeType.WRITE_POINT_REMOVED);
removed.setMessage("删除 MQ 投递点,原 value 类型: DutyImNotice");
KeyStructureChange key = new KeyStructureChange();
key.setKeyPattern("duty_im_notice_topic");
key.setChannel("ROCKETMQ");
key.setWriteLocation("DutyDelayQueueImNoticeService#addMq:43");
key.setValueType("DutyImNotice");
key.setOldSkeletonJson(skeleton);
key.setNewSkeletonJson("");
key.getFieldDetails().add(removed);
report.getKeyChanges().add(key);
String md = new ReportBuilder("[序列化结构变更]").toMarkdown(report);
assertTrue(md.contains("> **变更类型**: 删除写入点"), md);
assertTrue(md.contains("> **原消息体结构:**"), md);
assertTrue(md.contains("<font color=\"warning\">" + skeleton + "</font>"), md);
assertTrue(md.contains("(投递点已删除)"), md);
}
@Test
void fieldLevelChangeStillUsesFragmentHighlightNotWholeWrap() {
CheckReport report = baseReport();
report.getKeyChanges().add(simpleKey("k1", "{\"a\":\"\"}", "{\"a\":\"\",\"b\":\"\"}", "b"));
String md = new ReportBuilder("[序列化结构变更]").toMarkdown(report);
assertTrue(md.contains("> **value值由**"), md);
assertTrue(md.contains("> **变更为:**"), md);
assertTrue(md.contains("<font color=\"info\">\"b\":\"\"</font>"), md);
assertFalse(md.contains("<font color=\"info\">{\"a\":\"\",\"b\":\"\"}</font>"), md);
assertFalse(md.contains("变更类型"), md);
}
@Test
void unresolvedLongExpressionTruncated() {
StringBuilder expr = new StringBuilder("prefix.");
while (expr.length() < 100) {
expr.append("getVeryLongMethodName()");
}
CheckReport report = baseReport();
KeyStructureChange key = new KeyStructureChange();
key.setKeyPattern("unknown-key");
key.setKeyExpression(expr.toString());
key.setKeyUnresolved(true);
key.setOldSkeletonJson("{}");
key.setNewSkeletonJson("{\"a\":\"\"}");
SchemaChange added = new SchemaChange(ChangeType.FIELD_ADDED);
added.setFieldPath("a");
key.getFieldDetails().add(added);
report.getKeyChanges().add(key);
String md = new ReportBuilder("[序列化结构变更]").toMarkdown(report);
assertTrue(md.contains("...`"), "应截断并以 ... 结尾,实际:\n" + md);
assertTrue(md.contains("建议 manual_mappings 补充"), md);
assertFalse(md.contains(expr.toString()), "完整超长表达式不应出现");
}
@Test
void pathAwareNestedHighlight() {
String json = "{\"vo\":{\"dbName\":\"\",\"id\":\"\"},\"expiresAtMs\":0}";