PathrockNetwork Gno Explorer
HomeBlocksTransactionsTokensRealmsPackagesValidatorsAnalytics

PathrockNetwork Gno Explorer — an independent explorer for Gno.land Mainnet (gnoland-1), operated by PathrockNetwork. Not an official Gno.land service.

gnowebarchive RPC

gno.land/r/moul/reactions/v0

Realm
Open in gnoweb ↗

Overview

Kind
Realm (renderable)
Name
v0
Namespace
moul / reactions
Files
5 (README)(gnomod.toml)
Exported functions
10
Module
gno.land/r/moul/reactions/v0
gno
0.9

Files (5)

  • README.mdmarkdown
  • gnomod.tomltoml
  • reactions.gnogno
  • render.gnogno
  • reactions_test.gnogno
reactions_test.gnogno
1package reactions23import (4	"strconv"5	"strings"6	"testing"78	rx "gno.land/p/moul/reactions/v0"9	"gno.land/p/nt/testutils/v0"10	"gno.land/p/nt/uassert/v0"11)1213const homePage = "gno.land/r/moul/home"1415var (16	alice = testutils.TestAddress("alice")17	bob   = testutils.TestAddress("bob")18)1920// reset clears realm state. Realm globals live for the whole test binary, and21// the Example runs after every Test, so everything that renders starts here.22func reset() { board = rx.NewBoard() }2324func TestReactAndUnreact(cur realm, t *testing.T) {25	reset()2627	testing.SetRealm(testing.NewUserRealm(alice))28	React(cross(cur), homePage, rx.KeyUp)29	testing.SetRealm(testing.NewUserRealm(bob))30	React(cross(cur), homePage, rx.KeyFire)3132	uassert.Equal(t, 2, Count(homePage))33	uassert.Equal(t, 1, CountOf(homePage, rx.KeyUp))34	uassert.Equal(t, rx.KeyUp, ReactionOf(homePage, alice))35	uassert.Equal(t, 1, Pages())3637	key, who, _ := Last(homePage)38	uassert.Equal(t, rx.KeyFire, key)39	uassert.Equal(t, bob, who)4041	testing.SetRealm(testing.NewUserRealm(alice))42	Unreact(cross(cur), homePage)43	uassert.Equal(t, 1, Count(homePage))44	uassert.Equal(t, "", ReactionOf(homePage, alice))45}4647func TestReadsOnAnUntouchedPageAreZero(t *testing.T) {48	reset()49	uassert.Equal(t, 0, Count("gno.land/r/nobody/here"))50	uassert.Equal(t, 0, CountOf("gno.land/r/nobody/here", rx.KeyUp))51	uassert.Equal(t, "", ReactionOf("gno.land/r/nobody/here", alice))52	key, _, _ := Last("gno.land/r/nobody/here")53	uassert.Equal(t, "", key)54}5556func TestReactRefusals(cur realm, t *testing.T) {57	reset()58	testing.SetRealm(testing.NewUserRealm(alice))59	uassert.AbortsWithMessage(t, cur, "reactions: no such reaction: poop", func() {60		React(cross(cur), homePage, "poop")61	})6263	testing.SetRealm(testing.NewUserRealm(alice))64	uassert.AbortsWithMessage(t, cur, "reactions: not a page key: not a path", func() {65		React(cross(cur), "not a path", rx.KeyUp)66	})6768	uassert.Equal(t, 0, Pages(), "a refused reaction creates no page")69}7071// TestUnreactAbortsRatherThanNoOp is the deliberate asymmetry: a misspelled72// page key on Unreact has to be visible, or a reader thinks they removed73// something they did not.74func TestUnreactAbortsRatherThanNoOp(cur realm, t *testing.T) {75	reset()76	testing.SetRealm(testing.NewUserRealm(alice))77	uassert.AbortsWithMessage(t, cur, "reactions: nothing to remove on "+homePage, func() {78		Unreact(cross(cur), homePage)79	})80}8182// TestRenderBlockForIsWhatTheBlockLinksTo pins the property a host realm83// depends on: every link in the embedded block points at THIS realm, not at84// the realm that embedded it, and carries the page key as an argument.85func TestRenderBlockForIsWhatTheBlockLinksTo(t *testing.T) {86	reset()87	got := RenderBlockFor(homePage)88	uassert.True(t, strings.Contains(got, "(/r/moul/reactions/v0$help&func=React&"),89		"the txlink targets this realm")90	uassert.True(t, strings.Contains(got, "page=gno.land%2Fr%2Fmoul%2Fhome"),91		"and carries the host page as the parameter")92	uassert.False(t, strings.Contains(got, "/r/moul/home$help"),93		"never the host realm, which has no React to call")94}9596// TestRenderBlockKeysOnTheCaller is the borrowed-read rule this realm's whole97// ergonomics rest on: RenderBlock has no cur realm parameter, so gno opens no98// frame for it and unsafe.CurrentRealm() reports whoever called.99//100// In-package there is no other realm to call from, so what this pins is the101// half that can be pinned here: RenderBlock agrees with RenderBlockFor when102// the caller IS this realm. The cross-realm half is measured in AGENTS.md103// (2026-09-22) and is the same mechanism r/moul/config's TopBlock uses.104func TestRenderBlockKeysOnTheCaller(t *testing.T) {105	reset()106	uassert.Equal(t, RenderBlockFor(realmPath), RenderBlock())107	uassert.NotEqual(t, RenderBlockFor(homePage), RenderBlock(),108		"and a different page is a different block")109}110111func TestRenderPageView(cur realm, t *testing.T) {112	reset()113	testing.SetRealm(testing.NewUserRealm(alice))114	React(cross(cur), homePage, rx.KeyUp)115116	got := Render(homePage)117	uassert.True(t, strings.HasPrefix(got, "# gno\\.land/r/moul/home\n"),118		"the heading is the page key, escaped: ui.Inline backslashes the dot")119	uassert.True(t, strings.Contains(got, "Last reaction: \U0001F44D by "))120	uassert.True(t, strings.Contains(got, "Remove my reaction"))121	uassert.True(t, strings.Contains(got, "[The board](/r/moul/reactions/v0)"))122}123124func TestRenderRejectsAPathThatIsNotAPageKey(t *testing.T) {125	reset()126	got := Render("[click](http://e.vil)")127	uassert.True(t, strings.HasPrefix(got, "# Not a page\n"))128	uassert.False(t, strings.Contains(got, "](http://e.vil)"),129		"a render path is escaped before it is shown back")130}131132// TestRenderHomeShowsTheBoard uses uassert rather than an Example because the133// page contains consecutive blank lines, which gno collapses inside an134// // Output: block.135func TestRenderHomeShowsTheBoard(cur realm, t *testing.T) {136	reset()137	uassert.True(t, strings.Contains(Render(""), "*No page has been reacted to yet.*"))138139	testing.SetRealm(testing.NewUserRealm(alice))140	React(cross(cur), homePage, rx.KeyParty)141142	got := Render("")143	uassert.True(t, strings.Contains(got,144		"| [gno\\.land/r/moul/home](/r/moul/reactions/v0:gno.land/r/moul/home) | 1 |"),145		"the cell text is escaped, the URL is not: they are different contexts")146	uassert.True(t, strings.Contains(got, "import \"gno.land/r/moul/reactions/v0\""),147		"the homepage is the getting-started doc, and the snippet is copy-pasteable")148	for _, k := range rx.Keys() {149		uassert.True(t, strings.Contains(got, "| `"+k+"` | "+rx.Emoji(k)+" |"), k)150	}151}152153// TestBoardIndexIsCapped: the number of pages is unbounded, the index is not.154func TestBoardIndexIsCapped(cur realm, t *testing.T) {155	reset()156	for i := 0; i < maxListed+3; i++ {157		testing.SetRealm(testing.NewUserRealm(alice))158		// Zero-padded, because avl keys sort as strings and ufmt has no width159		// flags: "p9" would otherwise sort between "p10" and "p11".160		n := strconv.Itoa(i)161		if len(n) < 2 {162			n = "0" + n163		}164		React(cross(cur), "gno.land/r/spam/p"+n, rx.KeyUp)165	}166	uassert.Equal(t, maxListed+3, Pages())167168	got := Render("")169	uassert.Equal(t, maxListed, strings.Count(got, "(/r/moul/reactions/v0:gno.land/r/spam/"))170	uassert.True(t, strings.Contains(got, "28 pages in total, 25 shown."))171}172

Functions

  • Count(page string) int

  • CountOf(page string, key string) int

  • Last(page string) (key string, who string, height int64)

  • Pages() int

  • React(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}, page string, key string)

  • ReactionOf(page string, who string) string

  • Render(path string) string

  • RenderBlock() string

  • RenderBlockFor(page string) string

  • Unreact(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}, page string)

Signatures reconstructed verbatim from vm/qfuncs — interface params keep their inline definitions.

Rendered

RenderedRawgnoweb ↗

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.