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

render_test.gno

3.12 Kb · 94 lines
 1package bullscows
 2
 3import (
 4	"strings"
 5	"testing"
 6
 7	"gno.land/p/nt/uassert/v0"
 8)
 9
10// clear restores the globals to their init() state so assertions do not depend
11// on which tests ran first. Realm globals live for the whole test binary.
12func clear() {
13	round = 1
14	attempts = 0
15	history = nil
16	records = nil
17	secret = newSecret(seedFor(round))
18}
19
20// ExampleRender pins the fresh-round view: no guesses, empty leaderboard.
21func ExampleRender() {
22	clear()
23	print(Render(""))
24	// Output:
25	// # Bulls & Cows
26	//
27	// One shared secret 4-digit code (no repeated digits). Call `Guess("1972")` to get **bulls** (right digit, right spot) and **cows** (right digit, wrong spot). First to 4 bulls wins the round; `GiveUp()` reveals the code and starts over.
28	//
29	// ## Round 1
30	//
31	// Attempts so far: **0**
32	//
33	// _No guesses yet this round — be the first._
34	//
35	// ## Leaderboard (fastest solves)
36	//
37	// _Nobody has cracked a code yet._
38}
39
40// TestRenderHistoryNewestFirst checks the guess table is reverse-chronological.
41func TestRenderHistoryNewestFirst(t *testing.T) {
42	clear()
43	addHistory(guessLog{player: "alice", guess: "1234", bulls: 1, cows: 2})
44	addHistory(guessLog{player: "bob", guess: "5678", bulls: 0, cows: 1})
45
46	out := Render("")
47	uassert.True(t, strings.Contains(out, "### Recent guesses"), "history section should appear")
48	uassert.True(t, strings.Contains(out, "| `bob` | 5678 | 0 | 1 |\n| `alice` | 1234 | 1 | 2 |\n"),
49		"newest guess should be listed first")
50	uassert.False(t, strings.Contains(out, "_No guesses yet"), "empty-history notice should be gone")
51}
52
53// TestRenderLeaderboard checks solved records render in rank order.
54func TestRenderLeaderboard(t *testing.T) {
55	clear()
56	addRecord(record{player: "carol", attempts: 3, round: 1})
57	addRecord(record{player: "dave", attempts: 7, round: 2})
58
59	out := Render("")
60	uassert.True(t, strings.Contains(out, "| 1 | `carol` | 3 | 1 |\n| 2 | `dave` | 7 | 2 |\n"),
61		"leaderboard should rank fastest first")
62	uassert.False(t, strings.Contains(out, "_Nobody has cracked a code yet._"),
63		"empty-leaderboard notice should be gone")
64}
65
66// TestRenderShortensLongAddresses checks the bech32 addresses players actually
67// have get elided rather than blowing out the table.
68func TestRenderShortensLongAddresses(t *testing.T) {
69	clear()
70	long := "g1manfred47kzduec920z88wfr64ylksmdcedlf5"
71	addHistory(guessLog{player: long, guess: "1234", bulls: 0, cows: 0})
72
73	out := Render("")
74	uassert.False(t, strings.Contains(out, long), "full address should not be rendered")
75	uassert.True(t, strings.Contains(out, "| `"+long[:8]+"…"+long[len(long)-4:]+"` | 1234 |"),
76		"address should be shortened to prefix…suffix")
77}
78
79// TestRenderTracksRoundAndAttempts checks the counters reach the page.
80func TestRenderTracksRoundAndAttempts(t *testing.T) {
81	clear()
82	round = 4
83	attempts = 11
84
85	out := Render("")
86	uassert.True(t, strings.Contains(out, "## Round 4\n"), "round should be shown")
87	uassert.True(t, strings.Contains(out, "Attempts so far: **11**"), "attempts should be shown")
88}
89
90// TestRenderIgnoresPath documents that Render has no sub-routes.
91func TestRenderIgnoresPath(t *testing.T) {
92	clear()
93	uassert.Equal(t, Render(""), Render("/anything"))
94}