Files
ttstd-infinite-canvas/backend/internal/app/cloud_agent_layout_patch_test.go
AetherNo2332 6a216dddc2 perf(cloud-agent): 画布事件 - 整理类变更只下发几何增量
一次整理几十个节点时,canvas_updated 仍按整节点下发完整 before/after,单条事件会超过
validateCloudAgentRuntime 的 128KiB 单事件上限,整轮直接失败。

- 新增 cloudAgentShrinkChange:仅当 before/after 除 position/width/height/zIndex 之外
  完全一致(且无键被删)时,只下发 id 与变化的几何字段;带内容或 metadata 变化的节点仍发
  完整 before/after,不影响前端的三方合并与生成任务状态保护。
- 新增用例覆盖"几何变化只发增量"与"内容变化 / 键被删仍发完整对象"。
2026-09-22 01:32:32 +08:00

72 lines
3.2 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package app
import (
"encoding/json"
"reflect"
"strings"
"testing"
)
// geometryPatchFixture 造一对"只差位置"的重节点:正文很大,几何变化很小。
func geometryPatchFixture() (map[string]any, map[string]any) {
heavy := strings.Repeat("分镜行正文", 2000)
node := func(x, y float64, rows []any) map[string]any {
return map[string]any{
"id": "sb-1", "type": "script", "title": "第一场",
"position": map[string]any{"x": x, "y": y}, "width": 920.0, "height": 360.0,
"metadata": map[string]any{"storyboard": map[string]any{"rows": rows}, "status": "idle"},
}
}
return node(0, 0, []any{heavy}), node(120, 480, []any{heavy})
}
// 位置/尺寸变化只发几何增量:一次整理几十个分镜节点时,完整 before/after 会让单条
// canvas_updated 事件超过 validateCloudAgentRuntime 的 128KiB 单事件上限,整轮直接终止。
func TestCloudAgentGeometryOnlyChangeShrinksPatch(t *testing.T) {
before, after := geometryPatchFixture()
shrunkBefore, shrunkAfter := cloudAgentShrinkChange(before, after)
raw, _ := json.Marshal([]map[string]any{{"before": shrunkBefore, "after": shrunkAfter}})
if len(raw) > 512 {
t.Fatalf("几何增量仍然过大(%d 字节):%s", len(raw), raw)
}
if shrunkBefore["id"] != "sb-1" || shrunkAfter["id"] != "sb-1" {
t.Fatalf("增量必须带 id:%+v %+v", shrunkBefore, shrunkAfter)
}
if _, ok := shrunkAfter["position"]; !ok {
t.Fatalf("几何增量缺少 position:%+v", shrunkAfter)
}
if _, ok := shrunkAfter["metadata"]; ok {
t.Fatalf("几何增量不应携带正文字段:%+v", shrunkAfter)
}
// 新增节点(before 为空)没有可比对的旧值,不缩。
if _, kept := cloudAgentShrinkChange(nil, after); kept["metadata"] == nil {
t.Fatalf("新增节点不应被缩减:%+v", kept)
}
}
// 内容变化(正文 / metadata)仍发完整 before/after:前端按字段三方合并,缩成几何增量会
// 丢掉内容变化,也会影响前端对生成任务状态的保护逻辑。
func TestCloudAgentContentChangeKeepsFullPatch(t *testing.T) {
before, after := geometryPatchFixture()
contentAfter := map[string]any{
"id": "sb-1", "type": "script", "title": "第一场",
"position": after["position"], "width": 920.0, "height": 360.0,
"metadata": map[string]any{"storyboard": map[string]any{"rows": []any{"改过的行"}}, "status": "idle"},
}
keptBefore, keptAfter := cloudAgentShrinkChange(before, contentAfter)
if _, ok := keptAfter["metadata"]; !ok {
t.Fatalf("内容变化被错误地缩成几何增量:%+v", keptAfter)
}
if keptBefore["id"] != before["id"] || keptBefore["metadata"] == nil {
t.Fatalf("内容变化应保留完整 before:%+v", keptBefore)
}
// 键被删掉时同样不缩:只发几何字段会让前端无法区分"消失的字段"与"保持本地值"。
keyRemoved := map[string]any{"id": "sb-1", "type": "script", "title": "第一场", "position": after["position"]}
deletedBefore, deletedAfter := cloudAgentShrinkChange(before, keyRemoved)
if !reflect.DeepEqual(deletedBefore, before) || !reflect.DeepEqual(deletedAfter, keyRemoved) {
t.Fatalf("缺键的变更不应被缩成几何增量:%+v %+v", deletedBefore, deletedAfter)
}
}