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

polls_test.gno

3.76 Kb · 154 lines
  1package polls
  2
  3import (
  4	"strings"
  5	"testing"
  6
  7	"gno.land/p/nt/testutils/v0"
  8	"gno.land/p/nt/uassert/v0"
  9)
 10
 11var (
 12	alice = testutils.TestAddress("alice")
 13	bob   = testutils.TestAddress("bob")
 14	carol = testutils.TestAddress("carol")
 15)
 16
 17// resetState clears package-level state between tests so cases are independent.
 18func resetState() {
 19	polls = nil
 20	nextID = 0
 21}
 22
 23func TestParseOptions(t *testing.T) {
 24	tests := []struct {
 25		name  string
 26		input string
 27		want  []string
 28	}{
 29		{"simple", "a,b,c", []string{"a", "b", "c"}},
 30		{"trims spaces", " yes , no ", []string{"yes", "no"}},
 31		{"drops empties", "a,,b, ,c", []string{"a", "b", "c"}},
 32		{"single", "only", []string{"only"}},
 33		{"all blank", " , ,", nil},
 34	}
 35	for _, tt := range tests {
 36		got := parseOptions(tt.input)
 37		if len(got) != len(tt.want) {
 38			t.Errorf("%s: len = %d, want %d (%v)", tt.name, len(got), len(tt.want), got)
 39			continue
 40		}
 41		for i := range got {
 42			if got[i] != tt.want[i] {
 43				t.Errorf("%s: [%d] = %q, want %q", tt.name, i, got[i], tt.want[i])
 44			}
 45		}
 46	}
 47}
 48
 49func TestCreateAndVote(cur realm, t *testing.T) {
 50	resetState()
 51	testing.SetRealm(testing.NewUserRealm(alice))
 52
 53	id := CreatePoll(cross(cur), "Best chain?", "gno,eth,btc")
 54	if id != 0 {
 55		t.Fatalf("first poll id = %d, want 0", id)
 56	}
 57	if PollCount() != 1 {
 58		t.Fatalf("PollCount = %d, want 1", PollCount())
 59	}
 60
 61	// alice votes gno.
 62	Vote(cross(cur), id, 0)
 63
 64	// bob votes eth.
 65	testing.SetRealm(testing.NewUserRealm(bob))
 66	Vote(cross(cur), id, 1)
 67
 68	// carol votes gno.
 69	testing.SetRealm(testing.NewUserRealm(carol))
 70	Vote(cross(cur), id, 0)
 71
 72	p := getPoll(id)
 73	if p.Tallies[0] != 2 {
 74		t.Errorf("gno tally = %d, want 2", p.Tallies[0])
 75	}
 76	if p.Tallies[1] != 1 {
 77		t.Errorf("eth tally = %d, want 1", p.Tallies[1])
 78	}
 79	if total(p.Tallies) != 3 {
 80		t.Errorf("total = %d, want 3", total(p.Tallies))
 81	}
 82}
 83
 84func TestDoubleVotePanics(cur realm, t *testing.T) {
 85	resetState()
 86	testing.SetRealm(testing.NewUserRealm(alice))
 87
 88	id := CreatePoll(cross(cur), "Coffee or tea?", "coffee,tea")
 89	Vote(cross(cur), id, 0)
 90
 91	// A second vote by the same address aborts (cross-realm panic).
 92	uassert.AbortsWithMessage(t, cur, "address already voted on this poll", func() {
 93		Vote(cross(cur), id, 1)
 94	})
 95}
 96
 97func TestVoteBounds(cur realm, t *testing.T) {
 98	resetState()
 99	testing.SetRealm(testing.NewUserRealm(alice))
100
101	id := CreatePoll(cross(cur), "A or B?", "a,b")
102
103	uassert.AbortsWithMessage(t, cur, "option index out of range", func() {
104		Vote(cross(cur), id, 5)
105	})
106}
107
108func TestCreatePollNeedsTwoOptions(cur realm, t *testing.T) {
109	resetState()
110	testing.SetRealm(testing.NewUserRealm(alice))
111
112	uassert.AbortsWithMessage(t, cur, "a poll needs at least 2 options", func() {
113		CreatePoll(cross(cur), "One?", "only")
114	})
115}
116
117func TestRender(cur realm, t *testing.T) {
118	resetState()
119	testing.SetRealm(testing.NewUserRealm(alice))
120
121	// Empty index.
122	if got := Render(""); !strings.Contains(got, "No polls yet") {
123		t.Errorf("empty Render should mention no polls, got:\n%s", got)
124	}
125
126	id := CreatePoll(cross(cur), "Pick one", "x,y")
127	Vote(cross(cur), id, 0)
128
129	// Index lists the poll and bar chart glyphs.
130	idx := Render("")
131	if !strings.Contains(idx, "Pick one") {
132		t.Errorf("index missing question:\n%s", idx)
133	}
134	if !strings.Contains(idx, "▓") || !strings.Contains(idx, "░") {
135		t.Errorf("index missing bar glyphs:\n%s", idx)
136	}
137	if !strings.Contains(idx, "Total votes: 1") {
138		t.Errorf("index missing total votes:\n%s", idx)
139	}
140	if !strings.Contains(idx, "100%") {
141		t.Errorf("index missing 100%% for the sole vote:\n%s", idx)
142	}
143
144	// Single-poll path.
145	single := Render("0")
146	if !strings.Contains(single, "Poll #0") {
147		t.Errorf("single Render missing poll header:\n%s", single)
148	}
149
150	// Unknown path.
151	if got := Render("99"); !strings.Contains(got, "not found") {
152		t.Errorf("unknown poll should say not found, got:\n%s", got)
153	}
154}