Skip to content Search Apps Documentation Source Content File Folder Download Copy Actions State String Boolean Number Struct Map Slice Pointer Function Closure Reference Nil Package Type Interface Unknown

Community realm. Read the code first. Community realm, deployed by its author. Read the code before you interact or send coins.

svg_test.gno

5.66 Kb · 177 lines
  1package svg
  2
  3import (
  4	"strings"
  5	"testing"
  6
  7	"gno.land/p/nt/uassert/v0"
  8)
  9
 10func TestBaseAttrsEmpty(t *testing.T) {
 11	uassert.Equal(t, "", BaseAttrs{}.String())
 12}
 13
 14func TestBaseAttrsAllFields(t *testing.T) {
 15	b := BaseAttrs{
 16		ID:          "i",
 17		Class:       "c",
 18		Style:       "fill:red",
 19		Stroke:      "black",
 20		StrokeWidth: "2",
 21		Opacity:     "0.5",
 22		Transform:   "rotate(90)",
 23		Visibility:  "hidden",
 24	}
 25	uassert.Equal(t,
 26		`id="i" class="c" style="fill:red" stroke="black" stroke-width="2" opacity="0.5" transform="rotate(90)" visibility="hidden"`,
 27		b.String())
 28}
 29
 30func TestBaseAttrsSkipsEmptyFields(t *testing.T) {
 31	uassert.Equal(t, `id="i" opacity="0.5"`, BaseAttrs{ID: "i", Opacity: "0.5"}.String())
 32}
 33
 34func TestCircle(t *testing.T) {
 35	c := NewCircle(1, 2, 3, "red")
 36	uassert.Equal(t, `<circle cx="1" cy="2" r="3" fill="red" />`, c.String())
 37
 38	uassert.True(t, c.WithClass("dot") == c, "WithClass should be chainable: same pointer back")
 39	uassert.Equal(t, `<circle cx="1" cy="2" r="3" fill="red" class="dot"/>`, c.String())
 40}
 41
 42func TestEllipse(t *testing.T) {
 43	e := NewEllipse(4, 5, "blue")
 44	// NewEllipse takes no radii, so RX/RY stay zero until set directly.
 45	uassert.Equal(t, `<ellipse cx="4" cy="5" rx="0" ry="0" fill="blue" />`, e.String())
 46
 47	e.RX, e.RY = 10, 20
 48	e.WithClass("blob")
 49	uassert.Equal(t, `<ellipse cx="4" cy="5" rx="10" ry="20" fill="blue" class="blob"/>`, e.String())
 50}
 51
 52func TestRectangle(t *testing.T) {
 53	r := NewRectangle(1, 2, 30, 40, "green")
 54	uassert.Equal(t, `<rect x="1" y="2" width="30" height="40" rx="0" ry="0" fill="green" />`, r.String())
 55
 56	r.RX, r.RY = 5, 6
 57	r.WithClass("box")
 58	uassert.Equal(t, `<rect x="1" y="2" width="30" height="40" rx="5" ry="6" fill="green" class="box"/>`, r.String())
 59}
 60
 61func TestPath(t *testing.T) {
 62	p := NewPath("M0 0 L10 10", "none")
 63	uassert.Equal(t, `<path d="M0 0 L10 10" fill="none" />`, p.String())
 64
 65	p.WithClass("stroke")
 66	uassert.Equal(t, `<path d="M0 0 L10 10" fill="none" class="stroke"/>`, p.String())
 67}
 68
 69func TestPolygon(t *testing.T) {
 70	p := NewPolygon("0,0 10,0 5,8", "yellow")
 71	uassert.Equal(t, `<polygon points="0,0 10,0 5,8" fill="yellow" />`, p.String())
 72
 73	p.WithClass("tri")
 74	uassert.Equal(t, `<polygon points="0,0 10,0 5,8" fill="yellow" class="tri"/>`, p.String())
 75}
 76
 77func TestPolyline(t *testing.T) {
 78	p := NewPolyline("0,0 10,10", "none")
 79	uassert.Equal(t, `<polyline points="0,0 10,10" fill="none" />`, p.String())
 80
 81	p.WithClass("line")
 82	uassert.Equal(t, `<polyline points="0,0 10,10" fill="none" class="line"/>`, p.String())
 83}
 84
 85func TestText(t *testing.T) {
 86	tx := NewText(7, 8, "hello", "black")
 87	uassert.Equal(t, `<text x="7" y="8" dx="0" dy="0" rotate="" fill="black" >hello</text>`, tx.String())
 88
 89	tx.DX, tx.DY, tx.Rotate = 1, 2, "45"
 90	tx.WithClass("label")
 91	uassert.Equal(t, `<text x="7" y="8" dx="1" dy="2" rotate="45" fill="black" class="label">hello</text>`, tx.String())
 92}
 93
 94func TestGroup(t *testing.T) {
 95	g := NewGroup("purple")
 96	uassert.Equal(t, `<g fill="purple" ></g>`, g.String())
 97
 98	g.Append(NewCircle(0, 0, 1, "red"), NewPath("M0 0", "none"))
 99	g.WithClass("layer")
100	uassert.Equal(t,
101		`<g fill="purple" class="layer"><circle cx="0" cy="0" r="1" fill="red" /><path d="M0 0" fill="none" /></g>`,
102		g.String())
103}
104
105func TestGroupNesting(t *testing.T) {
106	inner := NewGroup("a")
107	inner.Append(NewCircle(1, 1, 1, "red"))
108	outer := NewGroup("b")
109	outer.Append(inner)
110
111	uassert.Equal(t,
112		`<g fill="b" ><g fill="a" ><circle cx="1" cy="1" r="1" fill="red" /></g></g>`,
113		outer.String())
114}
115
116func TestCanvasEmpty(t *testing.T) {
117	c := NewCanvas(100, 50)
118	uassert.Equal(t,
119		`<svg xmlns="http://www.w3.org/2000/svg" width="100" height="50" viewBox=""></svg>`,
120		c.String())
121}
122
123func TestCanvasWithViewBox(t *testing.T) {
124	c := NewCanvas(100, 50)
125	uassert.True(t, c.WithViewBox(0, 0, 200, 100) == c, "WithViewBox should be chainable")
126	uassert.True(t, strings.Contains(c.String(), `viewBox="0 0 200 100"`), "viewBox should be set")
127}
128
129func TestCanvasAppend(t *testing.T) {
130	c := NewCanvas(10, 10)
131	c.Append(NewCircle(1, 1, 1, "red"), NewCircle(2, 2, 2, "blue"))
132
133	out := c.String()
134	uassert.True(t, strings.Contains(out, `<circle cx="1" cy="1" r="1" fill="red" /><circle cx="2" cy="2" r="2" fill="blue" />`),
135		"elements should render in insertion order")
136}
137
138// TestCanvasStyleIsKeyOrdered is the determinism check that matters on-chain:
139// the style block must not depend on insertion order, or two nodes could
140// disagree on the rendered output.
141func TestCanvasStyleIsKeyOrdered(t *testing.T) {
142	a := NewCanvas(10, 10)
143	a.AddStyle("z-last", "fill:blue").AddStyle("a-first", "fill:red")
144
145	b := NewCanvas(10, 10)
146	b.AddStyle("a-first", "fill:red").AddStyle("z-last", "fill:blue")
147
148	uassert.Equal(t, a.String(), b.String())
149	uassert.True(t, strings.Contains(a.String(), `<style>a-first{fill:red}z-last{fill:blue}</style>`),
150		"styles should be emitted in key order")
151}
152
153func TestCanvasNoStyleBlockWhenUnset(t *testing.T) {
154	uassert.False(t, strings.Contains(NewCanvas(1, 1).String(), "<style>"),
155		"a canvas with no styles should not emit an empty <style> block")
156}
157
158func TestCanvasAddStyleChainable(t *testing.T) {
159	c := NewCanvas(1, 1)
160	uassert.True(t, c.AddStyle("a", "b") == c, "AddStyle should be chainable")
161}
162
163func TestCanvasBase64RoundTrip(t *testing.T) {
164	c := NewCanvas(10, 10)
165	c.Append(NewCircle(1, 1, 1, "red"))
166
167	// Base64 must encode exactly what String() produced.
168	uassert.Equal(t, "PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxMCIgaGVpZ2h0PSIxMCIgdmlld0JveD0iIj48Y2lyY2xlIGN4PSIxIiBjeT0iMSIgcj0iMSIgZmlsbD0icmVkIiAvPjwvc3ZnPg==",
169		c.Base64())
170}
171
172func TestCanvasRenderWrapsBase64(t *testing.T) {
173	c := NewCanvas(10, 10)
174	c.Append(NewCircle(1, 1, 1, "red"))
175
176	uassert.Equal(t, "![a picture](data:image/svg+xml;base64,"+c.Base64()+")", c.Render("a picture"))
177}