Search Apps Documentation Source Content File Folder Download Copy Actions Download State String Boolean Number Struct Map Slice Pointer Function Closure Reference Nil Package Type Interface Unknown

write_test.gno

4.12 Kb · 108 lines
  1package blog
  2
  3import (
  4	"strings"
  5	"testing"
  6
  7	"gno.land/p/nt/testutils/v0"
  8	"gno.land/p/nt/uassert/v0"
  9)
 10
 11var stranger = testutils.TestAddress("stranger")
 12
 13// Everything here goes through the real crossing functions rather than seed(),
 14// because the author check, the re-key on a date change and the panic messages
 15// only exist on that path and are exactly what a typo would break on a
 16// permanent path.
 17
 18func TestSetPublishesAndRenders(cur realm, t *testing.T) {
 19	reset()
 20	testing.SetRealm(testing.NewUserRealm(author))
 21	Set(cross(cur), "hello", "Hello", "2026-09-23", "Gno, tooling", "The body.")
 22
 23	uassert.Equal(t, 1, Count(), "one post")
 24	uassert.Equal(t, "The body.", Get("hello"), "the body round-trips")
 25	uassert.True(t, strings.Contains(Render("hello"), "# Hello"), "it renders")
 26	// Tags are normalized on write, not on read, so the hash the tool computed
 27	// locally is the hash the manifest reports.
 28	uassert.True(t, strings.Contains(Manifest(), "\t"+hashOf(record("Hello", "2026-09-23", "gno,tooling", "The body."))),
 29		"the manifest hashes the normalized record")
 30}
 31
 32func TestOnlyTheAuthorMayWrite(cur realm, t *testing.T) {
 33	reset()
 34	testing.SetRealm(testing.NewUserRealm(stranger))
 35	// AbortsWithMessage, not PanicsWithMessage: a panic that crosses a realm
 36	// boundary becomes an abort, which recover() cannot catch, so asserting it
 37	// as a panic does not fail the assertion, it kills the whole test binary.
 38	uassert.AbortsWithMessage(t, cur, "restricted to the author", func() {
 39		Set(cross(cur), "nope", "Nope", "2026-09-23", "", "Body.")
 40	})
 41	uassert.AbortsWithMessage(t, cur, "restricted to the author", func() {
 42		SetIntro(cross(cur), "mine now")
 43	})
 44	uassert.Equal(t, 0, Count(), "nothing was written")
 45}
 46
 47// The one case a second tree can get wrong: re-dating a post must MOVE its
 48// index entry, not leave a ghost at the old key rendering the post twice.
 49func TestSetRedatingMovesTheIndexEntry(cur realm, t *testing.T) {
 50	reset()
 51	testing.SetRealm(testing.NewUserRealm(author))
 52	Set(cross(cur), "a", "A", "2026-01-01", "", "Body A.")
 53	Set(cross(cur), "a", "A", "2026-12-31", "", "Body A.")
 54
 55	uassert.Equal(t, 1, Count(), "still one post")
 56	out := Render("")
 57	uassert.Equal(t, 1, strings.Count(out, "](/r/moul/blog:a)"), "listed exactly once")
 58	uassert.True(t, strings.Contains(out, "2026-12-31"), "under the new date")
 59	uassert.False(t, strings.Contains(out, "2026-01-01"), "and not the old one")
 60}
 61
 62func TestSetRejectsWhatTheToolRejects(cur realm, t *testing.T) {
 63	reset()
 64	testing.SetRealm(testing.NewUserRealm(author))
 65	uassert.AbortsContains(t, cur, "invalid slug", func() {
 66		Set(cross(cur), "Caps", "T", "2026-09-23", "", "Body.")
 67	})
 68	uassert.AbortsContains(t, cur, "reserved slug", func() {
 69		Set(cross(cur), introSlug, "T", "2026-09-23", "", "Body.")
 70	})
 71	uassert.AbortsContains(t, cur, "invalid date", func() {
 72		Set(cross(cur), "ok", "T", "23-09-2026", "", "Body.")
 73	})
 74	uassert.AbortsContains(t, cur, "a post needs a title", func() {
 75		Set(cross(cur), "ok", "  ", "2026-09-23", "", "Body.")
 76	})
 77	uassert.Equal(t, 0, Count(), "none of them was written")
 78}
 79
 80func TestAppendAndDelete(cur realm, t *testing.T) {
 81	reset()
 82	testing.SetRealm(testing.NewUserRealm(author))
 83	Set(cross(cur), "long", "Long", "2026-09-23", "", "First half.")
 84	Append(cross(cur), "long", " Second half.")
 85	uassert.Equal(t, "First half. Second half.", Get("long"), "append concatenates, it does not replace")
 86
 87	uassert.AbortsWithMessage(t, cur, `no such post: "ghost"`, func() {
 88		Append(cross(cur), "ghost", "x")
 89	})
 90
 91	Delete(cross(cur), "long")
 92	uassert.Equal(t, 0, Count(), "deleted")
 93	uassert.True(t, strings.Contains(Render(""), "Nothing published yet."), "and gone from the index")
 94	uassert.AbortsWithMessage(t, cur, `no such post: "long"`, func() {
 95		Delete(cross(cur), "long")
 96	})
 97}
 98
 99func TestRevisionMovesOnEveryWrite(cur realm, t *testing.T) {
100	reset()
101	testing.SetRealm(testing.NewUserRealm(author))
102	uassert.Equal(t, 0, Revision(), "a fresh realm is at zero")
103	Set(cross(cur), "a", "A", "2026-09-23", "", "Body.")
104	Append(cross(cur), "a", "!")
105	SetIntro(cross(cur), "# Header")
106	Delete(cross(cur), "a")
107	uassert.Equal(t, 4, Revision(), "one per mutation, so a client can tell nothing moved")
108}