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.

render_test.gno

4.98 Kb · 140 lines
  1package home
  2
  3import (
  4	"strings"
  5	"testing"
  6
  7	"gno.land/p/nt/uassert/v0"
  8)
  9
 10// Tests that need no crossing: pure helpers and the built-in views. The
 11// crossing behavior (writes, authority, theme lifecycle) is in home_test.gno,
 12// from outside the package, because a call into one's own realm never crosses.
 13
 14func TestValidSlug(t *testing.T) {
 15	for _, ok := range []string{"a", "now", "style.accent", "a-b_c.d", strings.Repeat("x", 64)} {
 16		uassert.True(t, validSlug(ok), ok)
 17	}
 18	for _, bad := range []string{"", "Now", "a:b", "a b", "a/b", strings.Repeat("x", 65)} {
 19		uassert.False(t, validSlug(bad), bad)
 20	}
 21}
 22
 23func TestFence(t *testing.T) {
 24	uassert.Equal(t, "```", fence("plain"))
 25	uassert.Equal(t, "```", fence("has `one` and ``two``"))
 26	uassert.Equal(t, "````", fence("```go\nx\n```"))
 27	uassert.Equal(t, "`````", fence("````"))
 28}
 29
 30func TestAttr(t *testing.T) {
 31	uassert.Equal(t, "a &amp; b &quot;c&quot; &lt;d&gt;\\n\\te", attr("a & b \"c\" <d>\r\n\te"))
 32}
 33
 34func TestFillerIsLazySinglePassAndOrderIndependent(t *testing.T) {
 35	ResetForTest()
 36	SeedForTest("a", "A says :b:")
 37	SeedForTest("b", "B")
 38	calls := 0
 39	f := NewFiller()
 40	f.Add("expensive", func() string { calls++; return "X" })
 41
 42	uassert.Equal(t, "A says :b: B :nope:", f.Fill(":a: :b: :nope:"))
 43	uassert.Equal(t, 0, calls, "an absent placeholder never runs its callback")
 44	uassert.Equal(t, "X", f.Fill(":expensive:"))
 45
 46	// A later Add for a slot's name wins: that is how a theme widget overrides.
 47	f.Add("a", func() string { return "widget" })
 48	uassert.Equal(t, "widget", f.Fill(":a:"))
 49}
 50
 51func TestRenderWithoutLayoutOrTheme(t *testing.T) {
 52	ResetForTest()
 53	out := Render("")
 54	uassert.True(t, strings.Contains(out, "# gno.land/r/g1lnkytfqcjwllws63gvf0mv9yt04aswy4y9amhm/home"), out)
 55	uassert.True(t, strings.Contains(out, "No theme is live"), out)
 56	uassert.True(t, strings.Contains(out, "_no slots yet_"), out)
 57	uassert.True(t, strings.Contains(out, "theme built-in"), out)
 58	uassert.False(t, strings.Contains(out, ":slots:"), "computed placeholders must resolve")
 59}
 60
 61func TestRenderLayoutSubstitution(t *testing.T) {
 62	ResetForTest()
 63	SeedForTest("intro", "Hello :rev: world") // placeholders inside a body stay put
 64	SeedForTest("layout", "# Page\n\n:intro:\n\nrev :rev: · :missing: · :realm:\n")
 65
 66	uassert.Equal(t, "# Page\n\nHello :rev: world\n\nrev 2 · :missing: · gno.land/r/g1lnkytfqcjwllws63gvf0mv9yt04aswy4y9amhm/home\n", Render(""))
 67}
 68
 69func TestRenderIndexAndSlot(t *testing.T) {
 70	ResetForTest()
 71	SeedForTest("now", "```go\nx := 1\n```")
 72
 73	idx := Render("slots")
 74	uassert.True(t, strings.Contains(idx, "| [now](/r/g1lnkytfqcjwllws63gvf0mv9yt04aswy4y9amhm/home:slots/now) |"), idx)
 75	uassert.True(t, strings.Contains(idx, "[edit](/r/g1lnkytfqcjwllws63gvf0mv9yt04aswy4y9amhm/home:edit/now)"), idx)
 76
 77	raw := Render("slots/now")
 78	uassert.True(t, strings.Contains(raw, "# now\n"), raw)
 79	uassert.True(t, strings.Contains(raw, "````\n```go\nx := 1\n```\n````\n"), "fence must outgrow the body: "+raw)
 80
 81	uassert.True(t, strings.Contains(Render("slots/nope"), "# Not found"))
 82	uassert.True(t, strings.Contains(Render("nope"), "# Not found"))
 83	uassert.True(t, strings.Contains(Render("slots?x=1"), "# Slots"), "query strings are ignored")
 84	uassert.Equal(t, Manifest(), Render("manifest"))
 85}
 86
 87func TestSlugsEachManifest(t *testing.T) {
 88	ResetForTest()
 89	SeedForTest("b", "two")
 90	SeedForTest("a", "one")
 91
 92	uassert.Equal(t, 2, len(Slugs()))
 93	uassert.Equal(t, "a", Slugs()[0])
 94
 95	visited := []string{}
 96	Each(func(slug string, s Slot) bool {
 97		visited = append(visited, slug+"="+s.Body)
 98		return false
 99	})
100	uassert.Equal(t, "a=one b=two", strings.Join(visited, " "))
101
102	lines := strings.Split(strings.TrimSpace(Manifest()), "\n")
103	uassert.Equal(t, 2, len(lines))
104	uassert.True(t, strings.HasPrefix(lines[0], "a\t2\t3\t"), lines[0])
105	uassert.Equal(t, 4, len(strings.Split(lines[0], "\t")))
106
107	s, ok := Lookup("a")
108	uassert.True(t, ok)
109	uassert.Equal(t, 2, s.Rev)
110	_, ok = Lookup("zzz")
111	uassert.False(t, ok)
112	uassert.Equal(t, "#000", Style("missing", "#000"))
113}
114
115func TestRenderEdit(t *testing.T) {
116	ResetForTest()
117	SeedForTest("intro", "line \"one\"\n<two> & three\ttab")
118
119	blank := Render("edit")
120	uassert.True(t, strings.Contains(blank, "<gno-form exec=\"Set\">"), blank)
121	uassert.True(t, strings.Contains(blank, "<gno-form exec=\"Delete\">"), blank)
122	uassert.True(t, strings.Contains(blank, "[edit](/r/g1lnkytfqcjwllws63gvf0mv9yt04aswy4y9amhm/home:edit/intro)"), blank)
123
124	one := Render("edit/intro")
125	uassert.True(t, strings.Contains(one, "value=\"intro\""), one)
126	uassert.True(t, strings.Contains(one,
127		"value=\"line &quot;one&quot;\\n&lt;two&gt; &amp; three\\ttab\""), one)
128
129	missing := Render("edit/later")
130	uassert.True(t, strings.Contains(missing, "Saving creates it"), missing)
131}
132
133func TestRenderSystem(t *testing.T) {
134	ResetForTest()
135	out := Render("system")
136	uassert.True(t, strings.Contains(out, "built-in fallback"), out)
137	uassert.True(t, strings.Contains(out, Admin.String()), out)
138	uassert.True(t, strings.Contains(out, "$help&func=Rollback"), out)
139	uassert.True(t, strings.Contains(out, "| last write | never |"), out)
140}