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/p/moul/x/wiki/v0

Package
Open in gnoweb ↗

Overview

Kind
Pure package
Name
v0
Namespace
moul / x / wiki
Files
18 (README)(gnomod.toml)
Exported functions
n/a — not supported for pure packages by the node (vm/qfuncs)
Module
gno.land/p/moul/x/wiki/v0
gno
0.9

Files (18)

  • README.mdmarkdown
  • gnomod.tomltoml
  • diff.gnogno
  • doc.gnogno
  • links.gnogno
  • page.gnogno
  • render.gnogno
  • revision.gnogno
  • talk.gnogno
  • title.gnogno
  • wiki.gnogno
  • diff_test.gnogno
  • limits_test.gnogno
  • links_test.gnogno
  • render_test.gnogno
  • talk_test.gnogno
  • title_test.gnogno
  • wiki_test.gnogno
  • talk_test.gnogno
    1package wiki23import (4	"strings"5	"testing"67	"gno.land/p/nt/uassert/v0"8

    Functions

    not supported for pure packages by the node (vm/qfuncs)

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

    )
    9
    10func comment(t *testing.T, w *Wiki, n int, author address, title, body string, replyTo uint64) *Comment {
    11 t.Helper()
    12 now, h := at(n)
    13 c, err := w.Comment(author, now, h, title, body, replyTo)
    14 uassert.NoError(t, err, title)
    15 return c
    16}
    17
    18func TestCommentThreads(t *testing.T) {
    19 w := New(3, DefaultMaxBody)
    20 edit(t, w, 1, alice, "A", "the article\n", "")
    21
    22 root1 := comment(t, w, 2, alice, "A", "First point.\n", 0)
    23 root2 := comment(t, w, 3, bob, "A", "Second point.\n", 0)
    24 reply := comment(t, w, 4, mod, "A", "Answering the first.\n", root1.ID)
    25
    26 title := MustParseTitle("A")
    27 uassert.Equal(t, 3, w.NumComments(title))
    28
    29 threads := w.Comments(title, 0, 10)
    30 uassert.Equal(t, 2, len(threads), "replies do not count as threads")
    31 uassert.Equal(t, uint64(root1.ID), threads[0].Root.ID)
    32 uassert.Equal(t, 1, len(threads[0].Replies))
    33 uassert.Equal(t, uint64(reply.ID), threads[0].Replies[0].ID)
    34 uassert.Equal(t, uint64(root2.ID), threads[1].Root.ID)
    35 uassert.Equal(t, 0, len(threads[1].Replies))
    36
    37 uassert.Equal(t, 1, len(w.Comments(title, 1, 10)), "offset skips whole threads")
    38}
    39
    40func TestCommentRejectsBadInput(t *testing.T) {
    41 w := New(3, DefaultMaxBody)
    42 edit(t, w, 1, alice, "A", "the article\n", "")
    43 now, h := at(2)
    44
    45 _, err := w.Comment(alice, now, h, "Missing page", "hi\n", 0)
    46 uassert.ErrorIs(t, err, ErrNoSuchPage, "a discussion needs a page to be about")
    47
    48 _, err = w.Comment(alice, now, h, "A", "", 0)
    49 uassert.ErrorIs(t, err, ErrEmptyComment)
    50
    51 _, err = w.Comment(alice, now, h, "A", strings.Repeat("x", MaxCommentLen+1), 0)
    52 uassert.ErrorIs(t, err, ErrCommentTooLong)
    53
    54 _, err = w.Comment(alice, now, h, "A", "hi\n", 999)
    55 uassert.ErrorIs(t, err, ErrNoSuchComment)
    56}
    57
    58// TestRepliesNestOneLevel pins MaxReplyDepth. Unbounded nesting means
    59// unbounded recursive rendering, which is the shape the query gas ceiling
    60// punishes hardest.
    61func TestRepliesNestOneLevel(t *testing.T) {
    62 w := New(3, DefaultMaxBody)
    63 edit(t, w, 1, alice, "A", "the article\n", "")
    64 root := comment(t, w, 2, alice, "A", "root\n", 0)
    65 reply := comment(t, w, 3, bob, "A", "reply\n", root.ID)
    66
    67 now, h := at(4)
    68 _, err := w.Comment(mod, now, h, "A", "reply to a reply\n", reply.ID)
    69 uassert.ErrorIs(t, err, ErrReplyToReply)
    70}
    71
    72func TestHideComment(t *testing.T) {
    73 w := New(3, DefaultMaxBody)
    74 edit(t, w, 1, alice, "A", "the article\n", "")
    75 before := w.Stats().BytesHeld
    76 c := comment(t, w, 2, bob, "A", "unpleasant\n", 0)
    77 uassert.Equal(t, before+len("unpleasant\n"), w.Stats().BytesHeld,
    78 "a comment costs its author the bytes it adds")
    79
    80 released, err := w.HideComment("A", c.ID)
    81 uassert.NoError(t, err)
    82 uassert.Equal(t, len("unpleasant\n"), released)
    83 uassert.Equal(t, before, w.Stats().BytesHeld)
    84
    85 threads := w.Comments(MustParseTitle("A"), 0, 10)
    86 uassert.Equal(t, 1, len(threads), "a hidden message stays in the thread")
    87 uassert.True(t, threads[0].Root.Hidden)
    88 uassert.Equal(t, "", threads[0].Root.Body)
    89
    90 // Hiding twice must not double-count the refund.
    91 released, err = w.HideComment("A", c.ID)
    92 uassert.NoError(t, err)
    93 uassert.Equal(t, 0, released)
    94 uassert.Equal(t, before, w.Stats().BytesHeld)
    95}
    96
    97func TestRenderTalk(t *testing.T) {
    98 w := New(3, DefaultMaxBody)
    99 edit(t, w, 1, alice, "A", "the article\n", "")
    100 root := comment(t, w, 2, alice, "A", "Is [[B]] the right link?\n", 0)
    101 comment(t, w, 3, bob, "A", "Yes.\n", root.ID)
    102 hidden := comment(t, w, 4, mod, "A", "spam\n", 0)
    103 w.HideComment("A", hidden.ID)
    104
    105 p, _ := w.Page("A")
    106 c := Ctx{Base: "/r/moul/x/wiki/v0", Exists: w.Exists}
    107 out := RenderTalk(c, w, p, 0, 10, act)
    108
    109 uassert.True(t, strings.Contains(out, "# Discussion: A"))
    110 uassert.True(t, strings.Contains(out, "func=Comment"), "an add-a-message action")
    111 uassert.True(t, strings.Contains(out, "Yes."), "replies render under their root")
    112 uassert.True(t, strings.Contains(out, "removed by a steward"))
    113 uassert.False(t, strings.Contains(out, "spam"), "a hidden body is gone from the render")
    114
    115 // A comment is user markdown too: it goes through the sanitizer, and it
    116 // is NOT a wikilink slot, so brackets stay literal rather than linking.
    117 uassert.True(t, strings.Contains(out, `\[\[B\]\]`), out)
    118}
    119
    120func TestRenderTalkEmpty(t *testing.T) {
    121 w := New(3, DefaultMaxBody)
    122 edit(t, w, 1, alice, "A", "the article\n", "")
    123 p, _ := w.Page("A")
    124 out := RenderTalk(Ctx{Base: "/r/moul/x/wiki/v0"}, w, p, 0, 10, nil)
    125 uassert.True(t, strings.Contains(out, "No messages yet"))
    126}
    127
    128func TestArticleLinksToItsDiscussion(t *testing.T) {
    129 w := New(3, DefaultMaxBody)
    130 edit(t, w, 1, alice, "A", "the article\n", "")
    131 comment(t, w, 2, alice, "A", "hi\n", 0)
    132
    133 p, _ := w.Page("A")
    134 out := RenderArticle(Ctx{Base: "/r/moul/x/wiki/v0"}, w, p, nil)
    135 uassert.True(t, strings.Contains(out, "[discussion](/r/moul/x/wiki/v0:A/talk) (1)"), out)
    136}
    137