Files
foundry-core/internal/platform/canvas_operations_test.go
codex-bot 19884b2a90
Foundry Go checks / check (push) Successful in 2m40s
Foundry Go checks / check (pull_request) Successful in 2m39s
Stage atomic canvas operation batches and durable receipts
2026-11-07 22:05:06 +08:00

64 lines
3.3 KiB
Go

package platform
import (
"encoding/json"
"testing"
)
const operationsFixture = `{"schema_version":2,"nodes":[{"id":"a","type":"plainText","position":{"x":0,"y":0},"width":240,"height":72,"data":{"kind":"plain-text","title":"original","text":"hello"}}],"edges":[],"viewport":{"x":0,"y":0,"zoom":1}}`
func TestCanvasOperationBatchStagesAndMerges(t *testing.T) {
initial := map[string]canvasSnapshot{"board": {BoardID: "board", Version: 7, Document: json.RawMessage(operationsFixture)}}
operations := []canvasOperation{
{ID: "11111111-1111-4111-8111-111111111111", Type: "node.patch", CanvasID: "board", ElementID: "a", Patch: map[string]json.RawMessage{"data": json.RawMessage(`{"title":"renamed"}`)}},
{ID: "22222222-2222-4222-8222-222222222222", Type: "node.patch", CanvasID: "board", ElementID: "a", Patch: map[string]json.RawMessage{"position": json.RawMessage(`{"x":90,"y":20}`)}},
}
result, err := applyCanvasOperations(initial, operations)
if err != nil {
t.Fatal(err)
}
if result["board"].Version != 8 {
t.Fatal("version did not advance once")
}
var document struct {
Nodes []struct {
Position struct{ X float64 }
Data struct {
Title string
Text string
}
}
}
if err = json.Unmarshal(result["board"].Document, &document); err != nil {
t.Fatal(err)
}
if document.Nodes[0].Data.Title != "renamed" || document.Nodes[0].Data.Text != "hello" || document.Nodes[0].Position.X != 90 {
t.Fatal("field merge lost unrelated content")
}
if string(initial["board"].Document) != operationsFixture {
t.Fatal("input snapshot mutated")
}
}
func TestCanvasOperationBatchRejectsWithoutPartialOutput(t *testing.T) {
initial := map[string]canvasSnapshot{"board": {BoardID: "board", Version: 1, Document: json.RawMessage(operationsFixture)}}
for _, operation := range []canvasOperation{
{ID: "11111111-1111-4111-8111-111111111111", Type: "node.patch", CanvasID: "board", ElementID: "a", Patch: map[string]json.RawMessage{"id": json.RawMessage(`"stolen"`)}},
{ID: "11111111-1111-4111-8111-111111111111", Type: "node.patch", CanvasID: "board", ElementID: "missing", Patch: map[string]json.RawMessage{"data": json.RawMessage(`{"title":"no"}`)}},
{ID: "11111111-1111-4111-8111-111111111111", Type: "edge.create", CanvasID: "board", ElementID: "edge", Record: json.RawMessage(`{"id":"edge","source":"a","target":"missing"}`)},
} {
if result, err := applyCanvasOperations(initial, []canvasOperation{operation}); err == nil || result != nil {
t.Fatal("invalid batch partially accepted")
}
}
}
func TestCanvasOperationBatchValidatesFinalGraphInsteadOfIntermediateState(t *testing.T) {
initial := map[string]canvasSnapshot{"board": {BoardID: "board", Version: 1, Document: json.RawMessage(operationsFixture)}}
operations := []canvasOperation{
{ID: "11111111-1111-4111-8111-111111111111", Type: "edge.create", CanvasID: "board", ElementID: "edge", Record: json.RawMessage(`{"id":"edge","source":"a","target":"b"}`)},
{ID: "22222222-2222-4222-8222-222222222222", Type: "node.create", CanvasID: "board", ElementID: "b", Record: json.RawMessage(`{"id":"b","type":"plainText","position":{"x":20,"y":20},"width":240,"height":72,"data":{"kind":"plain-text","title":"b","text":""}}`)},
}
if _, err := applyCanvasOperations(initial, operations); err != nil {
t.Fatal(err)
}
}