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

goldenticket_test.gno

4.30 Kb · 143 lines
  1package goldenticket
  2
  3import (
  4	"strings"
  5	"testing"
  6
  7	"gno.land/p/nt/grc721/v0"
  8	"gno.land/p/nt/testutils/v0"
  9	"gno.land/p/nt/uassert/v0"
 10)
 11
 12var (
 13	aliceAddr = testutils.TestAddress("alice")
 14	bobAddr   = testutils.TestAddress("bob")
 15)
 16
 17// reset redoes what init does on chain, with alice as the publisher.
 18func reset(cur realm) {
 19	func(cur realm) {
 20		bootstrap(aliceAddr, cur)
 21	}(cross(cur))
 22}
 23
 24// The reads, called as Adena calls them: the id a quoted string, two values.
 25func TestReads(cur realm, t *testing.T) {
 26	reset(cur)
 27
 28	owner, err := OwnerOf("1")
 29	uassert.NoError(t, err)
 30	uassert.Equal(t, aliceAddr, owner)
 31
 32	n, err := BalanceOf(aliceAddr)
 33	uassert.NoError(t, err)
 34	uassert.Equal(t, int64(1), n)
 35	n, err = BalanceOf(bobAddr)
 36	uassert.NoError(t, err)
 37	uassert.Equal(t, int64(0), n)
 38
 39	uri, err := TokenURI("1")
 40	uassert.NoError(t, err)
 41	uassert.Equal(t, defaultImage, uri)
 42	uassert.True(t, strings.HasPrefix(uri, "https://"))
 43
 44	meta, err := TokenMetadata("1")
 45	uassert.NoError(t, err)
 46	uassert.Equal(t, `{"name":"Golden Ticket #1","description":"A 1/1 on gno.land, minted to check that collections show in Adena.",`+
 47		`"image":"`+defaultImage+`","attributes":[{"traitType":"edition","value":"1 of 1"},{"traitType":"metal","value":"gold"}]}`, meta)
 48
 49	uassert.Equal(t, int64(1), Token.TotalSupply())
 50	uassert.Equal(t, "Golden Ticket", Name())
 51	uassert.Equal(t, "GOLD", Symbol())
 52
 53	// Any other id is an error, not a panic.
 54	for _, bad := range []grc721.TokenID{"", "0", "2", "01", " 1"} {
 55		_, err = OwnerOf(bad)
 56		uassert.ErrorContains(t, err, errNoTicket, string(bad))
 57		_, err = TokenURI(bad)
 58		uassert.ErrorContains(t, err, errNoTicket, string(bad))
 59		_, err = TokenMetadata(bad)
 60		uassert.ErrorContains(t, err, errNoTicket, string(bad))
 61	}
 62}
 63
 64func TestTransfer(cur realm, t *testing.T) {
 65	reset(cur)
 66
 67	// Only the holder moves the ticket.
 68	testing.SetRealm(testing.NewUserRealm(bobAddr))
 69	uassert.AbortsWithMessage(t, cur, errNotOwner, func() {
 70		Transfer(cross(cur), bobAddr)
 71	})
 72
 73	testing.SetRealm(testing.NewUserRealm(aliceAddr))
 74	uassert.AbortsWithMessage(t, cur, errBadOwner, func() {
 75		Transfer(cross(cur), address("nope"))
 76	})
 77	Transfer(cross(cur), bobAddr)
 78	owner, err := OwnerOf("1")
 79	uassert.NoError(t, err)
 80	uassert.Equal(t, bobAddr, owner)
 81	n, _ := BalanceOf(aliceAddr)
 82	uassert.Equal(t, int64(0), n)
 83	n, _ = BalanceOf(bobAddr)
 84	uassert.Equal(t, int64(1), n)
 85
 86	// Not through another realm.
 87	testing.SetRealm(testing.NewCodeRealm("gno.land/r/demo/relay"))
 88	uassert.AbortsWithMessage(t, cur, errNotOwner, func() {
 89		Transfer(cross(cur), aliceAddr)
 90	})
 91}
 92
 93func TestRender(cur realm, t *testing.T) {
 94	reset(cur)
 95	out := Render("")
 96	uassert.True(t, strings.Contains(out, "# Golden Ticket\n"))
 97	uassert.True(t, strings.Contains(out, "!["+tokenName+"]("+defaultImage+")"))
 98	uassert.True(t, strings.Contains(out, "Held by `"+aliceAddr.String()+"`."))
 99}
100
101func TestSetImage(cur realm, t *testing.T) {
102	reset(cur)
103	uassert.Equal(t, aliceAddr, Admin())
104	uassert.Equal(t, defaultImage, Image())
105
106	// Only the admin, and not through another realm.
107	testing.SetRealm(testing.NewUserRealm(bobAddr))
108	uassert.AbortsWithMessage(t, cur, errNotAdmin, func() {
109		SetImage(cross(cur), "https://example.org/a.png")
110	})
111	testing.SetRealm(testing.NewCodeRealm("gno.land/r/demo/relay"))
112	uassert.AbortsWithMessage(t, cur, errNotAdmin, func() {
113		SetImage(cross(cur), "https://example.org/a.png")
114	})
115
116	testing.SetRealm(testing.NewUserRealm(aliceAddr))
117	for _, bad := range []string{
118		"", "http://example.org/a.png", "https://", "javascript:alert(1)",
119		"https://example.org/a b.png", `https://example.org/"a.png`, "https://example.org/a.png)![x](y",
120		"https://example.org/" + strings.Repeat("a", 300),
121	} {
122		uassert.AbortsWithMessage(t, cur, errBadImage, func() {
123			SetImage(cross(cur), bad)
124		})
125	}
126
127	next := "https://ipfs.io/ipfs/bafy123/ticket.png?size=350&v=2"
128	SetImage(cross(cur), next)
129	uassert.Equal(t, next, Image())
130	uri, err := TokenURI("1")
131	uassert.NoError(t, err)
132	uassert.Equal(t, next, uri)
133	meta, _ := TokenMetadata("1")
134	uassert.True(t, strings.Contains(meta, `"image":"`+next+`"`))
135	uassert.True(t, strings.Contains(Render(""), "("+next+")"))
136
137	// The admin stays the publisher after the ticket moves.
138	Transfer(cross(cur), bobAddr)
139	testing.SetRealm(testing.NewUserRealm(bobAddr))
140	uassert.AbortsWithMessage(t, cur, errNotAdmin, func() {
141		SetImage(cross(cur), defaultImage)
142	})
143}