package platform import ( "encoding/json" "strconv" "testing" ) func memberFixture(t *testing.T) map[string]json.RawMessage { t.Helper() parent, children, err := migrateLegacyDocument(json.RawMessage(legacyMigrationFixture), map[string]string{"f": "11111111-1111-4111-8111-111111111111", "empty": "22222222-2222-4222-8222-222222222222"}) if err != nil { t.Fatal(err) } return map[string]json.RawMessage{"parent": parent, "11111111-1111-4111-8111-111111111111": children["f"], "22222222-2222-4222-8222-222222222222": children["empty"]} } func TestMembersMoveSiblingsAndRestoreParent(t *testing.T) { raw := memberFixture(t) a, b := "11111111-1111-4111-8111-111111111111", "22222222-2222-4222-8222-222222222222" first, err := moveMembersDocuments("parent", a, b, []string{"a"}, raw) if err != nil { t.Fatal(err) } if canvasNodeData(first[a])["a"] != nil || canvasNodeData(first[b])["a"] == nil { t.Fatal("member ownership copied rather than moved") } moved := canvasNodesByID(first[b])["a"]["position"].(map[string]any) if moved["x"] != float64(126) || moved["y"] != float64(224) { t.Fatalf("sibling coordinate conversion %v", moved) } second, err := moveMembersDocuments("parent", a, b, []string{"b"}, first) if err != nil { t.Fatal(err) } var child map[string]any _ = json.Unmarshal(second[b], &child) if len(child["edges"].([]any)) != 1 || child["edges"].([]any)[0].(map[string]any)["id"] != "internal" { t.Fatal("logical internal edge did not follow endpoints") } restored, err := moveMembersDocuments("parent", b, "parent", []string{"a", "b"}, second) if err != nil { t.Fatal(err) } nodes := canvasNodesByID(restored["parent"]) for id, pos := range map[string][2]float64{"a": {150, 260}, "b": {250, 300}} { p := nodes[id]["position"].(map[string]any) if p["x"] != pos[0] || p["y"] != pos[1] { t.Fatalf("%s did not restore position: %v", id, p) } } if nodes["a"]["data"].(map[string]any)["text"] != "preserved" { t.Fatal("content lost") } var parent map[string]any _ = json.Unmarshal(restored["parent"], &parent) if len(parent["edges"].([]any)) != 3 { t.Fatal("boundary edges lost") } if canvasNodeData(restored[a])["a"] != nil || canvasNodeData(restored[b])["a"] != nil { t.Fatal("duplicate content after move") } } func TestMembersRejectCollisionCyclesAndCapacity(t *testing.T) { raw := memberFixture(t) child := "11111111-1111-4111-8111-111111111111" if _, err := moveMembersDocuments("parent", "parent", child, []string{"f"}, raw); err != errGraphOwnership { t.Fatal("frame moved into itself") } if _, err := moveMembersDocuments("parent", child, "parent", []string{"a", "a"}, raw); err != errGraphOwnership { t.Fatal("duplicate member accepted") } var doc map[string]any _ = json.Unmarshal(raw["parent"], &doc) nodes := doc["nodes"].([]any) for len(nodes) < 500 { nodes = append(nodes, map[string]any{"id": "extra-" + strconv.Itoa(len(nodes)), "type": "material", "position": map[string]any{"x": 0, "y": 0}, "data": map[string]any{"kind": "text", "title": "", "text": ""}}) } doc["nodes"] = nodes raw["parent"], _ = json.Marshal(doc) saved := string(raw[child]) if _, err := moveMembersDocuments("parent", child, "parent", []string{"a"}, raw); err != errGraphCapacity { t.Fatalf("capacity failure: %v", err) } if string(raw[child]) != saved { t.Fatal("failed operation mutated input") } }