108 lines
4.5 KiB
Go
108 lines
4.5 KiB
Go
package platform
|
|
|
|
import (
|
|
"encoding/json"
|
|
"math"
|
|
"net/http/httptest"
|
|
"reflect"
|
|
"strconv"
|
|
"strings"
|
|
"testing"
|
|
)
|
|
|
|
func TestCanvasV2EdgeRoundTrip(t *testing.T) {
|
|
raw := strings.Replace(canvasFixture, `"schema_version":1`, `"schema_version":2`, 1)
|
|
data := `{"appearance":{"color":"#AA968B","width":2,"opacity":1,"line":"dashed","head":{"type":"triangle","size":12,"filled":true},"tail":{"type":"circle","size":8,"filled":false}},"animation":{"mode":"executing","effect":"flow","direction":"reverse","durationMs":1600,"color":"#FFFFFF"},"path":{"type":"bezier-chain","startControl":{"x":90,"y":0},"endControl":{"x":-90,"y":0},"knots":[{"id":"k1","position":{"x":450,"y":280},"in":{"x":-60,"y":0},"out":{"x":60,"y":0},"mode":"symmetric"}]},"execution":{"enabled":true}}`
|
|
raw = strings.Replace(raw, `"id":"e"`, `"data":`+data+`,"id":"e"`, 1)
|
|
out, ok := normalizeCanvas(json.RawMessage(raw))
|
|
if !ok {
|
|
t.Fatal("valid V2 rejected")
|
|
}
|
|
var doc map[string]any
|
|
_ = json.Unmarshal(out, &doc)
|
|
var expected any
|
|
_ = json.Unmarshal([]byte(data), &expected)
|
|
if !reflect.DeepEqual(doc["edges"].([]any)[0].(map[string]any)["data"], expected) {
|
|
t.Fatal("edge data lost")
|
|
}
|
|
cases := [][2]string{
|
|
{`"width":2`, `"width":21`}, {`"opacity":1`, `"opacity":0`},
|
|
{`"line":"dashed"`, `"line":"css"`}, {`"type":"triangle"`, `"type":"url(#marker)"`},
|
|
{`"durationMs":1600`, `"durationMs":249`}, {`"mode":"executing"`, `"mode":"running"`},
|
|
{`"x":60,"y":0`, `"x":60,"y":1`}, {`"x":60,"y":0`, `"x":-60,"y":0`},
|
|
{`"enabled":true`, `"enabled":"true"`}, {`"schema_version":2`, `"schema_version":1`},
|
|
}
|
|
for _, c := range cases {
|
|
if _, ok := normalizeCanvas(json.RawMessage(strings.Replace(raw, c[0], c[1], 1))); ok {
|
|
t.Errorf("accepted invalid replacement %s", c[1])
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestCanvasSchemaAccept(t *testing.T) {
|
|
for _, tc := range []struct {
|
|
accept string
|
|
want bool
|
|
}{
|
|
{"application/json", false}, {"application/vnd.foundry.canvas+json;version=2", true},
|
|
{"application/json, application/vnd.foundry.canvas+json; version=2", true},
|
|
{"application/vnd.foundry.canvas+json;version=2;q=0", false},
|
|
{"application/vnd.foundry.canvas+json;version=2;q=0.0", false},
|
|
{"application/vnd.foundry.canvas+json;version=2;q=NaN", false},
|
|
{"application/vnd.foundry.canvas+json;version=20", false},
|
|
} {
|
|
r := httptest.NewRequest("GET", "/", nil)
|
|
r.Header.Set("Accept", tc.accept)
|
|
if acceptsCanvasV2(r) != tc.want {
|
|
t.Error(tc.accept)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestCanvasV2CurveLimits(t *testing.T) {
|
|
knot := func(id string) map[string]any {
|
|
return map[string]any{"id": id, "position": map[string]any{"x": 0.0, "y": 0.0}, "in": map[string]any{"x": -1.0, "y": 0.0}, "out": map[string]any{"x": 1.0, "y": 0.0}, "mode": "smooth"}
|
|
}
|
|
for _, count := range []int{0, 1, 2, 64, 65} {
|
|
knots := []any{}
|
|
for i := 0; i < count; i++ {
|
|
knots = append(knots, knot(strconv.Itoa(i)))
|
|
}
|
|
data := map[string]any{"path": map[string]any{"type": "bezier-chain", "knots": knots}}
|
|
if validCanvasEdgeData(data) != (count <= 64) {
|
|
t.Errorf("knot count %d", count)
|
|
}
|
|
}
|
|
duplicate := map[string]any{"path": map[string]any{"type": "bezier-chain", "knots": []any{knot("same"), knot("same")}}}
|
|
if validCanvasEdgeData(duplicate) {
|
|
t.Fatal("duplicate knot ID")
|
|
}
|
|
for _, bad := range []float64{math.NaN(), math.Inf(1), math.Inf(-1), 1000001} {
|
|
k := knot("k")
|
|
k["position"].(map[string]any)["x"] = bad
|
|
if validCanvasEdgeData(map[string]any{"path": map[string]any{"type": "bezier-chain", "knots": []any{k}}}) {
|
|
t.Errorf("accepted non-finite/out-of-range coordinate %v", bad)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestCanvasV2AppearanceAndAnimationEnums(t *testing.T) {
|
|
for _, marker := range []string{"none", "open-arrow", "triangle", "circle", "diamond", "square"} {
|
|
for _, line := range []string{"solid", "dashed", "dotted"} {
|
|
data := map[string]any{"appearance": map[string]any{"line": line, "head": map[string]any{"type": marker, "size": 4.0, "filled": true}, "tail": map[string]any{"type": marker, "size": 32.0, "filled": false}}}
|
|
if !validCanvasEdgeData(data) {
|
|
t.Errorf("marker %s line %s rejected", marker, line)
|
|
}
|
|
}
|
|
}
|
|
for _, mode := range []string{"off", "always", "executing"} {
|
|
for _, effect := range []string{"flow", "dash", "pulse"} {
|
|
for _, direction := range []string{"forward", "reverse"} {
|
|
if !validCanvasEdgeData(map[string]any{"animation": map[string]any{"mode": mode, "effect": effect, "direction": direction, "durationMs": 30000.0, "color": "#FFFFFF"}}) {
|
|
t.Errorf("animation %s/%s/%s", mode, effect, direction)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|