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.

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}