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

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}