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.

numguess_test.gno

2.87 Kb · 115 lines
  1package numguess
  2
  3import (
  4	"strings"
  5	"testing"
  6
  7	"gno.land/p/nt/avl/v0"
  8)
  9
 10// resetGame re-initializes package globals so each test starts clean; init()
 11// runs only once for the whole test binary, and t.Run subtests don't reset it.
 12func resetGame(height int64) {
 13	current = newRound(1, height)
 14	attempts = avl.NewTree()
 15	leaderboard = nil
 16}
 17
 18func TestTargetFromHeight(t *testing.T) {
 19	tests := []struct {
 20		name   string
 21		height int64
 22	}{
 23		{"zero", 0},
 24		{"one", 1},
 25		{"large", 123456},
 26		{"negative", -42},
 27	}
 28	for _, tt := range tests {
 29		got := targetFromHeight(tt.height)
 30		if got < 1 || got > 100 {
 31			t.Errorf("%s: targetFromHeight(%d)=%d, want in 1..100", tt.name, tt.height, got)
 32		}
 33		// determinism: same input -> same output
 34		if again := targetFromHeight(tt.height); again != got {
 35			t.Errorf("%s: non-deterministic: %d != %d", tt.name, again, got)
 36		}
 37	}
 38}
 39
 40// TestGuessHigherLowerCorrect exercises the crossing Guess function, so it
 41// takes cur realm and calls through cross(cur).
 42func TestGuessHigherLowerCorrect(cur realm, t *testing.T) {
 43	resetGame(50)
 44	target := current.target
 45
 46	low := target - 1
 47	if low < 1 {
 48		low = 1
 49	}
 50	high := target + 1
 51	if high > 100 {
 52		high = 100
 53	}
 54
 55	if low != target {
 56		if got := Guess(cross(cur), low); got != "higher" {
 57			t.Errorf("Guess(%d) with target %d = %q, want higher", low, target, got)
 58		}
 59	}
 60	if high != target {
 61		if got := Guess(cross(cur), high); got != "lower" {
 62			t.Errorf("Guess(%d) with target %d = %q, want lower", high, target, got)
 63		}
 64	}
 65
 66	got := Guess(cross(cur), target)
 67	if got != "correct" {
 68		t.Fatalf("Guess(%d) = %q, want correct", target, got)
 69	}
 70	if !current.solved {
 71		t.Error("round should be solved after correct guess")
 72	}
 73	if len(leaderboard) != 1 {
 74		t.Errorf("leaderboard len = %d, want 1", len(leaderboard))
 75	}
 76}
 77
 78// TestNewRoundResets solves a round then verifies NewRound advances the round
 79// number and clears attempts.
 80func TestNewRoundResets(cur realm, t *testing.T) {
 81	resetGame(7)
 82	target := current.target
 83
 84	Guess(cross(cur), target) // solve it
 85	if !current.solved {
 86		t.Fatal("expected solved round")
 87	}
 88	prevRound := current.number
 89
 90	testing.SkipHeights(11) // change height so the next target can differ
 91	msg := NewRound(cross(cur))
 92	if current.number != prevRound+1 {
 93		t.Errorf("round number = %d, want %d", current.number, prevRound+1)
 94	}
 95	if current.solved {
 96		t.Error("fresh round should not be solved")
 97	}
 98	if totalAttempts() != 0 {
 99		t.Errorf("attempts should reset, got %d", totalAttempts())
100	}
101	if !strings.Contains(msg, "started") {
102		t.Errorf("NewRound message = %q, want it to mention 'started'", msg)
103	}
104}
105
106// TestRenderContainsState is a plain read — no cur.
107func TestRenderContainsState(t *testing.T) {
108	resetGame(3)
109	out := Render("")
110	for _, want := range []string{"Number Guessing Game", "Current round", "Leaderboard"} {
111		if !strings.Contains(out, want) {
112			t.Errorf("Render() missing %q", want)
113		}
114	}
115}