diff --git a/internal/platform/canvas_model_integration_test.go b/internal/platform/canvas_model_integration_test.go index 02d2d9d..0af23ff 100644 --- a/internal/platform/canvas_model_integration_test.go +++ b/internal/platform/canvas_model_integration_test.go @@ -370,4 +370,19 @@ func TestCanonicalModelMigrationAndIncrementalLifecycle(t *testing.T) { t.Fatal("compacted projection receipt was not recoverable by its original key") } + // A locally canceled incarnation was never sent; undo may first publish incarnation 2. + locallyElidedID := modelTestID(5201) + locallyRestored := modelTestNode(locallyElidedID, innerCanvas) + locallyRestored["incarnation"] = float64(2) + edit(1020, map[string]int64{innerCanvas: model.Versions[innerCanvas]}, modelChange{Kind: "element", ID: locallyElidedID, Before: modelJSON(nil), After: modelJSON(locallyRestored)}) + model = read() + if modelInt(model.Elements[locallyElidedID]["incarnation"]) != 2 || model.Tombstones[locallyElidedID] != 0 { + t.Fatal("local elision undo reused a canceled life or invented an ACK tombstone") + } + staleElisionKey := modelTestID(1021) + staleElision := modelBatch{ProtocolVersion: 2, RequestID: staleElisionKey, Expected: map[string]int64{innerCanvas: model.Versions[innerCanvas]}, Operations: []modelOperation{{ID: modelTestID(22007), Changes: []modelChange{{Kind: "field", Target: modelTarget{ID: locallyElidedID, Incarnation: 1}, Field: "data.title", Before: modelJSON(locallyElidedID), After: modelJSON("stale local callback")}}}}} + if call("POST", base+"/model/operations", staleElision, staleElisionKey, 409)["status"] != "not-applied" || !modelEqual(read().Elements[locallyElidedID], locallyRestored) { + t.Fatal("a callback from the locally canceled incarnation changed its restored successor") + } + }