render_test.gno
3.03 Kb · 86 lines
1package tictactoe
2
3import (
4 "strconv"
5 "strings"
6 "testing"
7
8 "gno.land/p/nt/uassert/v0"
9)
10
11// emptyRow is one rendered board row with no marks. The trailing space after
12// the final pipe is part of renderBoard's output — keep it.
13const emptyRow = "| · | · | · | \n"
14
15// TestRenderGame pins the exact single-game view. The game id is taken from
16// NewGame rather than hardcoded: realm globals persist across tests, so the
17// id depends on how many games earlier tests created.
18func TestRenderGame(cur realm, t *testing.T) {
19 testing.SetRealm(testing.NewUserRealm(alice))
20 id := NewGame(cross(cur), bob)
21
22 want := "# Tic-Tac-Toe — Game #" + strconv.Itoa(id) + "\n\n" +
23 "- X: `" + alice.String() + "`\n" +
24 "- O: `" + bob.String() + "`\n\n" +
25 emptyRow + emptyRow + emptyRow +
26 "\n**Turn: X**\n\n" +
27 "Cell indices:\n\n" +
28 "| 0 | 1 | 2 |\n| 3 | 4 | 5 |\n| 6 | 7 | 8 |\n"
29
30 uassert.Equal(t, want, Render("/"+strconv.Itoa(id)))
31}
32
33// TestRenderReflectsMoves checks the board and status track game state.
34func TestRenderReflectsMoves(cur realm, t *testing.T) {
35 testing.SetRealm(testing.NewUserRealm(alice))
36 id := NewGame(cross(cur), bob)
37 path := "/" + strconv.Itoa(id)
38
39 testing.SetRealm(testing.NewUserRealm(alice))
40 Move(cross(cur), id, 0)
41
42 out := Render(path)
43 uassert.True(t, strings.Contains(out, "| X | · | · | \n"), "X should appear in cell 0")
44 uassert.True(t, strings.Contains(out, "**Turn: O**"), "turn should pass to O")
45
46 testing.SetRealm(testing.NewUserRealm(bob))
47 Move(cross(cur), id, 4)
48 out = Render(path)
49 uassert.True(t, strings.Contains(out, "| X | · | · | \n| · | O | · | \n"), "O should appear in cell 4, below X")
50 uassert.True(t, strings.Contains(out, "**Turn: X**"), "turn should pass back to X")
51}
52
53// TestRenderFinishedStatus checks a decided game reports its winner.
54func TestRenderFinishedStatus(cur realm, t *testing.T) {
55 testing.SetRealm(testing.NewUserRealm(alice))
56 id := NewGame(cross(cur), bob)
57
58 // X takes the top row.
59 seq := []struct {
60 who address
61 cell int
62 }{{alice, 0}, {bob, 3}, {alice, 1}, {bob, 4}, {alice, 2}}
63 for _, s := range seq {
64 testing.SetRealm(testing.NewUserRealm(s.who))
65 Move(cross(cur), id, s.cell)
66 }
67
68 uassert.True(t, strings.Contains(Render("/"+strconv.Itoa(id)), "**Winner: X**"), "should report X as winner")
69}
70
71// TestRenderBadPaths covers the two error branches of Render.
72func TestRenderBadPaths(cur realm, t *testing.T) {
73 uassert.Equal(t, "# Tic-Tac-Toe\n\nInvalid game id: abc\n", Render("/abc"))
74 uassert.Equal(t, "# Tic-Tac-Toe\n\nGame 999999 not found.\n", Render("/999999"))
75}
76
77// TestRenderList checks the index lists games created in this run.
78func TestRenderList(cur realm, t *testing.T) {
79 testing.SetRealm(testing.NewUserRealm(alice))
80 id := NewGame(cross(cur), bob)
81
82 out := Render("")
83 uassert.True(t, strings.HasPrefix(out, "# Tic-Tac-Toe\n"), "expected the index header")
84 uassert.True(t, strings.Contains(out, "| # | X | O | Status |"), "expected the table header")
85 uassert.True(t, strings.Contains(out, "| "+strconv.Itoa(id)+" | `"+alice.String()+"`"), "expected the new game listed")
86}