memeland_test.gno
7.81 Kb ยท 282 lines
1package memeland
2
3import (
4 "strings"
5 "testing"
6 "time"
7
8 "gno.land/p/nt/testutils"
9 "gno.land/p/nt/uassert"
10 "gno.land/p/nt/ufmt"
11)
12
13func TestPostMeme(t *testing.T) {
14 m := NewMemeland()
15 id := m.PostMeme("Test meme data", time.Now().Unix())
16 uassert.NotEqual(t, "", string(id), "Expected valid ID, got empty string")
17}
18
19func TestGetPostsInRangePagination(t *testing.T) {
20 m := NewMemeland()
21 now := time.Now()
22
23 numOfPosts := 5
24 var memeData []string
25 for i := 1; i <= numOfPosts; i++ {
26 // Prepare meme data
27 nextTime := now.Add(time.Duration(i) * time.Minute)
28 data := ufmt.Sprintf("Meme #%d", i)
29 memeData = append(memeData, data)
30
31 m.PostMeme(data, nextTime.Unix())
32 }
33
34 // Get timestamps
35 beforeEarliest := now.Add(-1 * time.Minute)
36 afterLatest := now.Add(time.Duration(numOfPosts)*time.Minute + time.Minute)
37
38 testCases := []struct {
39 page int
40 pageSize int
41 expectedNumOfPosts int
42 }{
43 {page: 1, pageSize: 1, expectedNumOfPosts: 1}, // one per page
44 {page: 2, pageSize: 1, expectedNumOfPosts: 1}, // one on second page
45 {page: 1, pageSize: numOfPosts, expectedNumOfPosts: numOfPosts}, // all posts on single page
46 {page: 12, pageSize: 1, expectedNumOfPosts: 0}, // empty page
47 {page: 1, pageSize: numOfPosts + 1, expectedNumOfPosts: numOfPosts}, // page with fewer posts than its size
48 {page: 5, pageSize: numOfPosts / 5, expectedNumOfPosts: 1}, // evenly distribute posts per page
49 }
50
51 for _, tc := range testCases {
52 t.Run(ufmt.Sprintf("Page%d_Size%d", tc.page, tc.pageSize), func(t *testing.T) {
53 result := m.GetPostsInRange(beforeEarliest.Unix(), afterLatest.Unix(), tc.page, tc.pageSize, "DATE_CREATED")
54
55 // Count posts by how many times id: shows up in JSON string
56 postCount := strings.Count(result, `"id":"`)
57 uassert.Equal(t, tc.expectedNumOfPosts, postCount)
58 })
59 }
60}
61
62func TestGetPostsInRangeByTimestamp(t *testing.T) {
63 m := NewMemeland()
64 now := time.Now()
65
66 numOfPosts := 5
67 var memeData []string
68 for i := 1; i <= numOfPosts; i++ {
69 // Prepare meme data
70 nextTime := now.Add(time.Duration(i) * time.Minute)
71 data := ufmt.Sprintf("Meme #%d", i)
72 memeData = append(memeData, data)
73
74 m.PostMeme(data, nextTime.Unix())
75 }
76
77 // Get timestamps
78 beforeEarliest := now.Add(-1 * time.Minute)
79 afterLatest := now.Add(time.Duration(numOfPosts)*time.Minute + time.Minute)
80
81 // Default sort is by addition order/timestamp
82 jsonStr := m.GetPostsInRange(
83 beforeEarliest.Unix(), // start at earliest post
84 afterLatest.Unix(), // end at latest post
85 1, // first page
86 numOfPosts, // all memes on the page
87 "DATE_CREATED", // sort by newest first
88 )
89
90 uassert.NotEmpty(t, jsonStr, "Expected non-empty JSON string, got empty string")
91
92 // Count the number of posts returned in the JSON string as a rudimentary check for correct pagination/filtering
93 postCount := strings.Count(jsonStr, `"id":"`)
94 uassert.Equal(t, uint64(m.MemeCounter), uint64(postCount))
95
96 // Check if data is there
97 for _, expData := range memeData {
98 check := strings.Contains(jsonStr, expData)
99 uassert.True(t, check, ufmt.Sprintf("Expected %s in the JSON string, but counld't find it", expData))
100 }
101
102 // Check if ordering is correct, sort by created date
103 for i := 0; i < len(memeData)-2; i++ {
104 check := strings.Index(jsonStr, memeData[i]) >= strings.Index(jsonStr, memeData[i+1])
105 uassert.True(t, check, ufmt.Sprintf("Expected %s to be before %s, but was at %d, and %d", memeData[i], memeData[i+1], i, i+1))
106 }
107}
108
109func TestGetPostsInRangeByUpvote(t *testing.T) {
110 m := NewMemeland()
111 now := time.Now()
112
113 memeData1 := "Meme #1"
114 memeData2 := "Meme #2"
115
116 // Create posts at specific times for testing
117 id1 := m.PostMeme(memeData1, now.Unix())
118 id2 := m.PostMeme(memeData2, now.Add(time.Minute).Unix())
119
120 m.Upvote(id1)
121 m.Upvote(id2)
122
123 // Change caller so avoid double upvote panic
124 alice := testutils.TestAddress("alice")
125 testing.SetRealm(testing.NewUserRealm(alice))
126 m.Upvote(id1)
127
128 // Final upvote count:
129 // Meme #1 - 2 upvote
130 // Meme #2 - 1 upvotes
131
132 // Get timestamps
133 beforeEarliest := now.Add(-time.Minute)
134 afterLatest := now.Add(time.Hour)
135
136 // Default sort is by addition order/timestamp
137 jsonStr := m.GetPostsInRange(
138 beforeEarliest.Unix(), // start at earliest post
139 afterLatest.Unix(), // end at latest post
140 1, // first page
141 2, // all memes on the page
142 "UPVOTES", // sort by upvote
143 )
144
145 uassert.NotEmpty(t, jsonStr, "Expected non-empty JSON string, got empty string")
146
147 // Count the number of posts returned in the JSON string as a rudimentary check for correct pagination/filtering
148 postCount := strings.Count(jsonStr, `"id":"`)
149 uassert.Equal(t, uint64(m.MemeCounter), uint64(postCount))
150
151 // Check if ordering is correct
152 check := strings.Index(jsonStr, "Meme #1") <= strings.Index(jsonStr, "Meme #2")
153 uassert.True(t, check, ufmt.Sprintf("Expected %s to be before %s", memeData1, memeData2))
154}
155
156func TestBadSortBy(t *testing.T) {
157 m := NewMemeland()
158 now := time.Now()
159
160 numOfPosts := 5
161 var memeData []string
162 for i := 1; i <= numOfPosts; i++ {
163 // Prepare meme data
164 nextTime := now.Add(time.Duration(i) * time.Minute)
165 data := ufmt.Sprintf("Meme #%d", i)
166 memeData = append(memeData, data)
167
168 m.PostMeme(data, nextTime.Unix())
169 }
170
171 // Get timestamps
172 beforeEarliest := now.Add(-1 * time.Minute)
173 afterLatest := now.Add(time.Duration(numOfPosts)*time.Minute + time.Minute)
174
175 tests := []struct {
176 name string
177 sortBy string
178 wantPanic string
179 }{
180 {
181 name: "Empty sortBy",
182 sortBy: "",
183 wantPanic: "runtime error: index out of range",
184 },
185 {
186 name: "Wrong sortBy",
187 sortBy: "random string",
188 wantPanic: "",
189 },
190 }
191
192 for _, tc := range tests {
193 t.Run(tc.name, func(t *testing.T) {
194 defer func() {
195 if r := recover(); r == nil {
196 t.Errorf("code did not panic when it should have")
197 }
198 }()
199
200 // Panics should be caught
201 _ = m.GetPostsInRange(beforeEarliest.Unix(), afterLatest.Unix(), 1, 1, tc.sortBy)
202 })
203 }
204}
205
206func TestNoPosts(t *testing.T) {
207 m := NewMemeland()
208
209 // Add a post to Memeland
210 now := time.Now().Unix()
211
212 jsonStr := m.GetPostsInRange(0, now, 1, 1, "DATE_CREATED")
213
214 uassert.Equal(t, jsonStr, "[]")
215}
216
217func TestUpvote(t *testing.T) {
218 m := NewMemeland()
219
220 // Add a post to Memeland
221 now := time.Now().Unix()
222 postID := m.PostMeme("Test meme data", now)
223
224 // Initial upvote count should be 0
225 post := m.getPost(postID)
226 uassert.Equal(t, 0, post.UpvoteTracker.Size())
227
228 // Upvote the post
229 upvoteResult := m.Upvote(postID)
230 uassert.Equal(t, "upvote successful", upvoteResult)
231
232 // Retrieve the post again and check the upvote count
233 post = m.getPost(postID)
234 uassert.Equal(t, 1, post.UpvoteTracker.Size())
235}
236
237func TestDelete(t *testing.T) {
238 alice := testutils.TestAddress("alice")
239 testing.SetRealm(testing.NewUserRealm(alice))
240
241 // Alice is admin
242 m := NewMemeland()
243
244 // Set caller to Bob
245 bob := testutils.TestAddress("bob")
246 testing.SetRealm(testing.NewUserRealm(bob))
247
248 // Bob adds post to Memeland
249 now := time.Now()
250 postID := m.PostMeme("Meme #1", now.Unix())
251
252 // Alice removes Bob's post
253 testing.SetRealm(testing.NewUserRealm(alice))
254
255 id := m.RemovePost(postID)
256 uassert.Equal(t, postID, id, "post IDs not matching")
257 uassert.Equal(t, 0, len(m.Posts), "there should be 0 posts after removing")
258}
259
260func TestDeleteByNonAdmin(t *testing.T) {
261 alice := testutils.TestAddress("alice")
262 testing.SetRealm(testing.NewUserRealm(alice))
263
264 m := NewMemeland()
265
266 // Add a post to Memeland
267 now := time.Now()
268 postID := m.PostMeme("Meme #1", now.Unix())
269
270 // Bob will try to delete meme posted by Alice, which should fail
271 bob := testutils.TestAddress("bob")
272 testing.SetRealm(testing.NewUserRealm(bob))
273
274 defer func() {
275 if r := recover(); r == nil {
276 t.Errorf("code did not panic when it should have")
277 }
278 }()
279
280 // Should panic - caught by defer
281 m.RemovePost(postID)
282}