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.

home_test.gno

6.63 Kb · 177 lines
  1package home
  2
  3import (
  4	"strings"
  5	"testing"
  6
  7	"gno.land/p/nt/avl/v0"
  8	"gno.land/p/nt/testutils/v0"
  9	"gno.land/p/nt/uassert/v0"
 10)
 11
 12var (
 13	alice   = testutils.TestAddress("alice")
 14	bob     = testutils.TestAddress("bob")
 15	mallory = testutils.TestAddress("mallory")
 16)
 17
 18func reset() {
 19	galleries = avl.NewTree()
 20	slots = avl.NewTree()
 21	rev = 0
 22	hearts = avl.NewTree()
 23	recent = nil
 24}
 25
 26func seed(slug, body string) {
 27	rev++
 28	slots.Set(slug, &slot{body: body, rev: rev})
 29}
 30
 31func TestDefaultPageRendersEverySection(t *testing.T) {
 32	// State as left by init: every default slot, no heart yet.
 33	page := Render("")
 34	for _, want := range []string{"data:image/svg+xml;base64,", "Founder, CEO & CTO", "## 今 Now", "## 組 Inside Memba", "BARRICADE", "256 merged pull requests", "Paris P2P Festival", "Contributing on Gno since | 2022", "## 源 Open source", "(https://www.youtube.com/watch?v=aG4M37FX4II)", "**0** hearts so far.", "gno.land/r/g1747t5m2f08plqjlrjk2q0qld7465hxz8gkx59c/home"} {
 35		uassert.True(t, strings.Contains(page, want), "missing: "+want)
 36	}
 37	for _, s := range defaultSlots {
 38		uassert.False(t, strings.Contains(page, ":"+s.slug+":"), "unfilled placeholder :"+s.slug+":")
 39	}
 40	for _, g := range defaultGalleries {
 41		uassert.False(t, strings.Contains(page, ":gallery."+g.name+":"), "unfilled gallery :gallery."+g.name+":")
 42	}
 43	uassert.False(t, strings.Contains(page, ":hero:"))
 44}
 45
 46func TestSetGetDelete(cur realm, t *testing.T) {
 47	reset()
 48	testing.SetRealm(testing.NewUserRealm(admin))
 49
 50	Set(cross(cur), "bio", "Building on gno.")
 51	uassert.Equal(t, "Building on gno.", Get("bio"))
 52	Append(cross(cur), "bio", " Still.")
 53	uassert.Equal(t, "Building on gno. Still.", Get("bio"))
 54	uassert.Equal(t, 2, Revision())
 55
 56	Delete(cross(cur), "bio")
 57	uassert.Equal(t, "", Get("bio"))
 58	uassert.AbortsWithMessage(t, cur, "no such slot: bio", func() {
 59		Delete(cross(cur), "bio")
 60	})
 61}
 62
 63func TestWritesAreAdminOnly(cur realm, t *testing.T) {
 64	reset()
 65	testing.SetRealm(testing.NewUserRealm(mallory))
 66	uassert.AbortsWithMessage(t, cur, "restricted to admin", func() { Set(cross(cur), "bio", "pwned") })
 67	uassert.AbortsWithMessage(t, cur, "restricted to admin", func() { Append(cross(cur), "bio", "pwned") })
 68	uassert.AbortsWithMessage(t, cur, "restricted to admin", func() { Delete(cross(cur), "bio") })
 69}
 70
 71func TestSlugRules(cur realm, t *testing.T) {
 72	reset()
 73	testing.SetRealm(testing.NewUserRealm(admin))
 74	uassert.AbortsContains(t, cur, "invalid slug", func() { Set(cross(cur), "Bad", "x") })
 75	uassert.AbortsContains(t, cur, "invalid slug", func() { Set(cross(cur), "a:b", "x") })
 76	uassert.AbortsContains(t, cur, "invalid slug", func() { Set(cross(cur), "", "x") })
 77	uassert.AbortsWithMessage(t, cur, "reserved slug: hearts", func() { Set(cross(cur), "hearts", "fake 9999") })
 78	uassert.AbortsContains(t, cur, "reserved slug: gallery.", func() { Set(cross(cur), "gallery.x", "fake") })
 79}
 80
 81func TestFillIsSinglePass(t *testing.T) {
 82	reset()
 83	seed("layout", "A :a: B :missing: C 10:30 :b:")
 84	seed("a", "[:b:]")
 85	seed("b", "bee")
 86	uassert.Equal(t, "A [:b:] B :missing: C 10:30 bee", Render(""))
 87}
 88
 89func TestFallbackLayout(t *testing.T) {
 90	reset()
 91	seed("bio", "hi")
 92	uassert.True(t, strings.HasPrefix(Render(""), "# zôÖma\n\nhi\n\n**0** hearts"))
 93}
 94
 95func TestHeartOncePerAddress(cur realm, t *testing.T) {
 96	reset()
 97	seed("layout", ":hearts:")
 98
 99	testing.SetRealm(testing.NewUserRealm(alice))
100	Heart(cross(cur))
101	uassert.Equal(t, 1, Hearts())
102	uassert.True(t, HasHeart(alice))
103	uassert.AbortsWithMessage(t, cur, "already sent: one <3 per address", func() { Heart(cross(cur)) })
104
105	testing.SetRealm(testing.NewUserRealm(bob))
106	Heart(cross(cur))
107	uassert.Equal(t, 2, Hearts())
108	uassert.Equal(t, bob, recent[0], "newest first")
109
110	page := Render("")
111	uassert.True(t, strings.Contains(page, "**2** hearts so far."))
112	uassert.True(t, strings.Contains(page, "/u/"+bob.String()))
113	uassert.True(t, strings.Contains(Render("hearts"), "/u/"+alice.String()))
114}
115
116func TestRecentIsBounded(cur realm, t *testing.T) {
117	reset()
118	for i := 0; i < maxRecent+3; i++ {
119		testing.SetRealm(testing.NewUserRealm(testutils.TestAddress("fan" + string(rune('a'+i)))))
120		Heart(cross(cur))
121	}
122	uassert.Equal(t, maxRecent+3, Hearts())
123	uassert.Equal(t, maxRecent, len(recent))
124}
125
126func TestOtherViews(t *testing.T) {
127	reset()
128	seed("bio", "hello")
129	uassert.True(t, strings.Contains(Render("slots"), "[bio]"))
130	uassert.True(t, strings.Contains(Render("slots/bio"), "hello"))
131	uassert.True(t, strings.Contains(Render("slots/nope"), "Not found"))
132	uassert.True(t, strings.Contains(Render("nope"), "Not found"))
133}
134
135func TestGallery(cur realm, t *testing.T) {
136	reset()
137	seed("layout", ":gallery.demo:")
138
139	testing.SetRealm(testing.NewUserRealm(mallory))
140	uassert.AbortsWithMessage(t, cur, "restricted to admin", func() {
141		SetGallery(cross(cur), "demo", "film | A | b | https://x.y")
142	})
143
144	testing.SetRealm(testing.NewUserRealm(admin))
145	uassert.AbortsContains(t, cur, "needs 4 or 5 fields", func() { SetGallery(cross(cur), "demo", "film | A | b") })
146	uassert.AbortsContains(t, cur, "must be https://", func() { SetGallery(cross(cur), "demo", "film | A | b | javascript:alert(1)") })
147	uassert.AbortsContains(t, cur, "markdown would break", func() { SetGallery(cross(cur), "demo", "film | A | b | https://x.y/a)b") })
148
149	SetGallery(cross(cur), "demo", "# comment\nfilm | One <&> | meta | https://a.b/1\nproduct | Two | m | /r/x\nevent | Three | m | https://a.b/3\nreport | Four | m | https://a.b/4")
150	page := Render("")
151	uassert.Equal(t, 2, strings.Count(page, "<gno-columns>"), "3 per row")
152	uassert.Equal(t, 4, strings.Count(page, "data:image/svg+xml;base64,"))
153	uassert.True(t, strings.Contains(page, "](https://a.b/1)"))
154	uassert.True(t, strings.Contains(page, "](/r/x)"))
155
156	// Titles are XML-escaped inside the poster.
157	svg := poster(card{kind: "film", title: "One <&>", meta: "m", url: "https://a.b"})
158	uassert.True(t, strings.Contains(svg, "One &lt;&amp;&gt;"))
159
160	// An optional fifth field becomes the link's hover text.
161	SetGallery(cross(cur), "demo", "memba | DAO Management | m | https://a.b/dao | Vote, execute, create.")
162	uassert.True(t, strings.Contains(Render(""), `](https://a.b/dao "Vote, execute, create.")`))
163	uassert.Equal(t, "MEMBA · PRODUCT", styleOf("memba").label, "every seeded kind has its own style")
164	uassert.AbortsContains(t, cur, "without quotes", func() {
165		SetGallery(cross(cur), "demo", "memba | A | m | https://a.b | say \"hi\"")
166	})
167
168	DeleteGallery(cross(cur), "demo")
169	uassert.Equal(t, ":gallery.demo:", Render(""), "a missing gallery stays visible")
170}
171
172func TestWrap(t *testing.T) {
173	uassert.Equal(t, 1, len(wrap("Short title", 24)))
174	lines := wrap("The Underground Sistine Chapel is a very long title indeed", 24)
175	uassert.Equal(t, 2, len(lines))
176	uassert.True(t, strings.HasSuffix(lines[1], "…"))
177}