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 & b "c" <d>\\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 "one"\\n<two> & 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}