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

Community realm. Read the code first. Community realm, deployed by its author. Read the code before you interact or send coins.

tamagotchi_test.gno

3.69 Kb · 170 lines
  1package tamagotchi
  2
  3import (
  4	"strings"
  5	"testing"
  6
  7	"gno.land/p/nt/avl/v0"
  8	"gno.land/p/nt/testutils/v0"
  9)
 10
 11func resetState() {
 12	pets = avl.Tree{}
 13}
 14
 15func TestClamp(t *testing.T) {
 16	if clamp(150, 0, 100) != 100 {
 17		t.Fatal("clamp should cap at hi")
 18	}
 19	if clamp(-5, 0, 100) != 0 {
 20		t.Fatal("clamp should floor at lo")
 21	}
 22	if clamp(50, 0, 100) != 50 {
 23		t.Fatal("clamp should pass through in-range values")
 24	}
 25}
 26
 27func TestHatchCreatesLivingPet(t *testing.T) {
 28	resetState()
 29	alice := testutils.TestAddress("alice")
 30
 31	hatch(alice, "Fluffy", 100)
 32
 33	p, ok := get(alice)
 34	if !ok || !p.alive {
 35		t.Fatal("expected a living pet after hatch")
 36	}
 37	if p.name != "Fluffy" {
 38		t.Fatalf("expected name Fluffy, got %s", p.name)
 39	}
 40}
 41
 42func TestHatchTwiceWhileAlivePanics(t *testing.T) {
 43	resetState()
 44	alice := testutils.TestAddress("alice")
 45	hatch(alice, "Fluffy", 100)
 46
 47	defer func() {
 48		if r := recover(); r == nil {
 49			t.Fatal("expected panic hatching a second living pet")
 50		}
 51	}()
 52	hatch(alice, "Again", 101)
 53}
 54
 55func TestHatchAfterDeathKeepsLifetimeStats(t *testing.T) {
 56	resetState()
 57	alice := testutils.TestAddress("alice")
 58	hatch(alice, "Fluffy", 0)
 59	feed(alice, 0)
 60
 61	p, _ := get(alice)
 62	p.alive = false
 63	p.deaths = 1
 64
 65	hatch(alice, "Fluffy2", 10)
 66
 67	p, _ = get(alice)
 68	if p.feeds != 1 || p.deaths != 1 {
 69		t.Fatalf("expected lifetime stats to carry over, got feeds=%d deaths=%d", p.feeds, p.deaths)
 70	}
 71	if !p.alive {
 72		t.Fatal("expected the new pet to be alive")
 73	}
 74}
 75
 76func TestFeedReducesHunger(t *testing.T) {
 77	resetState()
 78	alice := testutils.TestAddress("alice")
 79	hatch(alice, "Fluffy", 100)
 80
 81	p, _ := get(alice)
 82	p.hunger = 60
 83
 84	feed(alice, 100)
 85	if p.hunger != 30 {
 86		t.Fatalf("expected hunger 30 after feed, got %d", p.hunger)
 87	}
 88	if p.feeds != 1 {
 89		t.Fatalf("expected feeds counter to increment, got %d", p.feeds)
 90	}
 91}
 92
 93func TestPlayRefusesWhenTooTired(t *testing.T) {
 94	resetState()
 95	alice := testutils.TestAddress("alice")
 96	hatch(alice, "Fluffy", 100)
 97
 98	p, _ := get(alice)
 99	p.energy = 5
100
101	out := play(alice, 100)
102	if !strings.Contains(out, "too tired") {
103		t.Fatalf("expected too-tired message, got %q", out)
104	}
105	if p.plays != 0 {
106		t.Fatal("play should not have counted while too tired")
107	}
108}
109
110func TestNeglectKillsPet(t *testing.T) {
111	resetState()
112	alice := testutils.TestAddress("alice")
113	hatch(alice, "Fluffy", 0)
114
115	defer func() {
116		if r := recover(); r == nil {
117			t.Fatal("expected panic acting on a neglected/dead pet")
118		}
119	}()
120	// Feed re-ticks against a much later height, starving the pet to death.
121	feed(alice, 1000)
122}
123
124func TestFeedWithoutPetPanics(t *testing.T) {
125	resetState()
126	bob := testutils.TestAddress("bob")
127
128	defer func() {
129		if r := recover(); r == nil {
130			t.Fatal("expected panic feeding without a pet")
131		}
132	}()
133	feed(bob, 100)
134}
135
136func TestRenderShowsEmptyThenPet(t *testing.T) {
137	resetState()
138	if !strings.Contains(Render(""), "No pets hatched yet") {
139		t.Fatal("expected empty-state placeholder")
140	}
141
142	alice := testutils.TestAddress("alice")
143	hatch(alice, "Fluffy", 100)
144
145	out := Render("")
146	if !strings.Contains(out, "Fluffy") {
147		t.Fatal("expected pet name in leaderboard render")
148	}
149
150	detail := Render(alice.String())
151	if !strings.Contains(detail, "Hunger") {
152		t.Fatal("expected detail card to show hunger stat")
153	}
154}
155
156// TestHatchViaCrossingCall smoke-tests the exported, realm-crossing entry
157// point end to end (as an on-chain caller would invoke it).
158func TestHatchViaCrossingCall(cur realm, t *testing.T) {
159	resetState()
160	alice := testutils.TestAddress("alice")
161	testing.SetRealm(testing.NewUserRealm(alice))
162
163	msg := Hatch(cross(cur), "Fluffy")
164	if !strings.Contains(msg, "hatched") {
165		t.Fatalf("expected hatch confirmation, got %q", msg)
166	}
167	if _, ok := get(alice); !ok {
168		t.Fatal("expected pet to be persisted for caller")
169	}
170}