Kind Realm (renderable)
Name home
Namespace g1lnkytfqcjwllws63gvf0mv9yt04aswy4y9amhm
Exported functions 30
Module gno.land/r/g1lnkytfqcjwllws63gvf0mv9yt04aswy4y9amhm/home
gno 0.9 render_test.gno gno
⧉
1 package home 2 3 import ( 4 "strings" 5 "testing" 6 7 "gno.land/p/nt/uassert/v0" 8 Accept (cur interface {.seal func(); Address func() .uverse.address; IsCode func() bool; IsCurrent func() bool; IsEphemeral func() bool; IsUser func() bool; IsUserCall func() bool; IsUserRun func() bool; PkgPath func() string; Previous func() .uverse.realm; String func() string; Sub func(string) .uverse.realm; Subpath func() string}, pkgPath string)
Append (cur interface {.seal func(); Address func() .uverse.address; IsCode func() bool; IsCurrent func() bool; IsEphemeral func() bool; IsUser func() bool; IsUserCall func() bool; IsUserRun func() bool; PkgPath func() string; Previous func() .uverse.realm; String func() string; Sub func(string) .uverse.realm; Subpath func() string}, slug string, body string)
Authority () string
Delete (cur interface {.seal func(); Address func() .uverse.address; IsCode func() bool; IsCurrent func() bool; IsEphemeral func() bool; IsUser func() bool; IsUserCall func() bool; IsUserRun func() bool; PkgPath func() string; Previous func() .uverse.realm; String func() string; Sub func(string) .uverse.realm; Subpath func() string}, slug string)
Each (fn func(string, gno.land/r/g1lnkytfqcjwllws63gvf0mv9yt04aswy4y9amhm/home.Slot) bool)
Fallback (path string) string
Forget (cur interface {.seal func(); Address func() .uverse.address; IsCode func() bool; IsCurrent func() bool; IsEphemeral func() bool; IsUser func() bool; IsUserCall func() bool; IsUserRun func() bool; PkgPath func() string; Previous func() .uverse.realm; String func() string; Sub func(string) .uverse.realm; Subpath func() string})
Freeze (cur interface {.seal func(); Address func() .uverse.address; IsCode func() bool; IsCurrent func() bool; IsEphemeral func() bool; IsUser func() bool; IsUserCall func() bool; IsUserRun func() bool; PkgPath func() string; Previous func() .uverse.realm; String func() string; Sub func(string) .uverse.realm; Subpath func() string})
Frozen () bool
Get (slug string) string
Has (slug string) bool
HistoryPaths () []string
LastHeight () int64
Layout () string
Link (sub string) string
LivePath () string
Lookup (slug string) (struct{Body string; Rev int; Height int64}, bool)
Manifest () string
NewFiller () *gno.land/r/g1lnkytfqcjwllws63gvf0mv9yt04aswy4y9amhm/home.Filler
Path () string
PendingPaths () []string
Register (cur interface {.seal func(); Address func() .uverse.address; IsCode func() bool; IsCurrent func() bool; IsEphemeral func() bool; IsUser func() bool; IsUserCall func() bool; IsUserRun func() bool; PkgPath func() string; Previous func() .uverse.realm; String func() string; Sub func(string) .uverse.realm; Subpath func() string}, t interface {Render func(string) string})
Render (path string) string
Revision () int
Rollback (cur interface {.seal func(); Address func() .uverse.address; IsCode func() bool; IsCurrent func() bool; IsEphemeral func() bool; IsUser func() bool; IsUserCall func() bool; IsUserRun func() bool; PkgPath func() string; Previous func() .uverse.realm; String func() string; Sub func(string) .uverse.realm; Subpath func() string})
Set (cur interface {.seal func(); Address func() .uverse.address; IsCode func() bool; IsCurrent func() bool; IsEphemeral func() bool; IsUser func() bool; IsUserCall func() bool; IsUserRun func() bool; PkgPath func() string; Previous func() .uverse.realm; String func() string; Sub func(string) .uverse.realm; Subpath func() string}, slug string, body string)
Slugs () []string
Style (key string, fallback string) string
TransferAuthority (cur interface {.seal func(); Address func() .uverse.address; IsCode func() bool; IsCurrent func() bool; IsEphemeral func() bool; IsUser func() bool; IsUserCall func() bool; IsUserRun func() bool; PkgPath func() string; Previous func() .uverse.realm; String func() string; Sub func(string) .uverse.realm; Subpath func() string}, to string)
Withdraw (cur interface {.seal func(); Address func() .uverse.address; IsCode func() bool; IsCurrent func() bool; IsEphemeral func() bool; IsUser func() bool; IsUserCall func() bool; IsUserRun func() bool; PkgPath func() string; Previous func() .uverse.realm; String func() string; Sub func(string) .uverse.realm; Subpath func() string}, pkgPath string)
Signatures reconstructed verbatim from vm/qfuncs — interface params keep their inline definitions.
)
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
14 func 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
23 func 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
30 func TestAttr(t *testing.T) {
31 uassert.Equal(t, "a & b "c" <d>\\n\\te" , attr( "a & b \"c\" <d>\r\n\te" ))
32 }
33
34 func 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
51 func 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
61 func 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
69 func 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
87 func 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
115 func 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
133 func 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 }
141
vm/qrender output, sanitized (docs/render-security.md) and displayed in an empty-sandbox iframe — scripts, forms and popups cannot run. Links stay inert in-preview; right-click to open.