一次整理几十个节点时,canvas_updated 仍按整节点下发完整 before/after,单条事件会超过 validateCloudAgentRuntime 的 128KiB 单事件上限,整轮直接失败。 - 新增 cloudAgentShrinkChange:仅当 before/after 除 position/width/height/zIndex 之外 完全一致(且无键被删)时,只下发 id 与变化的几何字段;带内容或 metadata 变化的节点仍发 完整 before/after,不影响前端的三方合并与生成任务状态保护。 - 新增用例覆盖"几何变化只发增量"与"内容变化 / 键被删仍发完整对象"。
72 lines
3.2 KiB
Go
72 lines
3.2 KiB
Go
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)
|
||
}
|
||
}
|