Search Apps Documentation Source Content File Folder Download Copy Actions Download

post_test.gno

9.70 Kb · 384 lines
  1package boards2
  2
  3import (
  4	"strings"
  5	"testing"
  6
  7	"gno.land/p/nt/testutils"
  8	"gno.land/p/nt/uassert"
  9	"gno.land/p/nt/ufmt"
 10)
 11
 12func TestPostFlag(t *testing.T) {
 13	addr := testutils.TestAddress("creator")
 14	post := createTestThread(t)
 15
 16	uassert.True(t, post.Flag(addr, "foo"))
 17	uassert.False(t, post.Flag(addr, "foo"), "should reject flag from duplicate user")
 18	uassert.Equal(t, post.FlagsCount(), 1)
 19}
 20
 21func TestPostRepost(t *testing.T) {
 22	// TODO: Improve this unit test
 23	addr := testutils.TestAddress("creatorDstBoard")
 24	perms := createBasicBoardPermissions(addr)
 25	cases := []struct {
 26		name, title, body string
 27		dstBoard          *Board
 28		thread            *Post
 29		setup             func() *Post
 30		err               string
 31	}{
 32		{
 33			name:     "repost thread",
 34			title:    "Repost Title",
 35			body:     "Repost body",
 36			dstBoard: newBoard(42, "dst123", addr, perms),
 37			setup:    func() *Post { return createTestThread(t) },
 38		},
 39		{
 40			name:  "invalid repost from reply",
 41			setup: func() *Post { return createTestReply(t) },
 42			err:   "post must be a thread to be reposted to another board",
 43		},
 44	}
 45
 46	for _, tc := range cases {
 47		t.Run(tc.name, func(t *testing.T) {
 48			var (
 49				repost  *Post
 50				creator = testutils.TestAddress("repostCreator")
 51				thread  = tc.setup()
 52			)
 53
 54			createRepost := func() {
 55				repost = thread.Repost(creator, tc.dstBoard, tc.title, tc.body)
 56			}
 57
 58			if tc.err != "" {
 59				uassert.PanicsWithMessage(t, tc.err, createRepost)
 60				return
 61			} else {
 62				uassert.NotPanics(t, createRepost)
 63			}
 64
 65			r, found := tc.dstBoard.GetThread(repost.ID)
 66			uassert.True(t, found)
 67			uassert.True(t, repost == r)
 68			uassert.Equal(t, tc.title, repost.Title)
 69			uassert.Equal(t, tc.body, repost.Body)
 70			uassert.Equal(t, uint(thread.Board.ID), uint(repost.RepostBoardID))
 71		})
 72	}
 73}
 74
 75func TestNewThread(t *testing.T) {
 76	testing.SetRealm(testing.NewCodeRealm("gno.land/r/gnoland/boards2/v1"))
 77
 78	creator := testutils.TestAddress("creator")
 79	title := "Test Title"
 80	body := strings.Repeat("A", 82)
 81	boardID := BoardID(1)
 82	threadID := PostID(42)
 83	boardName := "test123"
 84	perms := createBasicBoardPermissions(creator)
 85	board := newBoard(boardID, boardName, creator, perms)
 86	url := ufmt.Sprintf(
 87		"/r/gnoland/boards2/v1:%s/%d",
 88		boardName,
 89		uint(threadID),
 90	)
 91	replyURL := ufmt.Sprintf(
 92		"/r/gnoland/boards2/v1$help&func=CreateReply&boardID=%d&body=&replyID=0&threadID=%d",
 93		uint(boardID),
 94		uint(threadID),
 95	)
 96	editURL := ufmt.Sprintf(
 97		"/r/gnoland/boards2/v1$help&func=EditThread&boardID=%d&body=%s&threadID=%d&title=%s",
 98		uint(boardID),
 99		body,
100		uint(threadID),
101		strings.ReplaceAll(title, " ", "+"),
102	)
103	repostURL := ufmt.Sprintf(
104		"/r/gnoland/boards2/v1$help&func=CreateRepost&boardID=%d&body=&destinationBoardID=&threadID=%d&title=",
105		uint(boardID),
106		uint(threadID),
107	)
108	deleteURL := ufmt.Sprintf(
109		"/r/gnoland/boards2/v1$help&func=DeleteThread&boardID=%d&threadID=%d",
110		uint(boardID),
111		uint(threadID),
112	)
113	flagURL := ufmt.Sprintf(
114		"/r/gnoland/boards2/v1$help&func=FlagThread&boardID=%d&reason=&threadID=%d",
115		uint(boardID),
116		uint(threadID),
117	)
118
119	thread := newPost(board, threadID, threadID, creator, title, body)
120
121	uassert.True(t, thread.IsThread())
122	uassert.Equal(t, uint(threadID), uint(thread.ID))
123	uassert.False(t, thread.CreatedAt().IsZero())
124	uassert.True(t, thread.UpdatedAt.IsZero())
125	uassert.Equal(t, title, thread.Title)
126	uassert.Equal(t, body[:77]+"...", thread.Summary())
127	uassert.False(t, thread.HasReplies())
128	uassert.Equal(t, url, makeThreadURI(thread))
129	uassert.Equal(t, replyURL, makeCreateReplyURI(thread))
130	uassert.Equal(t, editURL, makeEditPostURI(thread))
131	uassert.Equal(t, repostURL, makeCreateRepostURI(thread))
132	uassert.Equal(t, deleteURL, makeDeletePostURI(thread))
133	uassert.Equal(t, flagURL, makeFlagURI(thread))
134}
135
136func TestThreadAddReply(t *testing.T) {
137	replier := testutils.TestAddress("replier")
138	thread := createTestThread(t)
139	threadID := uint(thread.ID)
140	body := "A reply"
141
142	reply := thread.AddReply(replier, body)
143
144	r, found := thread.GetReply(reply.ID)
145	uassert.True(t, found)
146	uassert.True(t, reply == r)
147	uassert.Equal(t, threadID+1, uint(reply.ID))
148	uassert.Equal(t, reply.Creator, replier)
149	uassert.Equal(t, reply.Body, body)
150	uassert.True(t, thread.HasReplies())
151}
152
153func TestThreadGetReply(t *testing.T) {
154	cases := []struct {
155		name   string
156		thread *Post
157		setup  func(thread *Post) (replyID PostID)
158		found  bool
159	}{
160		{
161			name:   "found",
162			thread: createTestThread(t),
163			setup: func(thread *Post) PostID {
164				reply := thread.AddReply(testutils.TestAddress("replier"), "")
165				return reply.ID
166			},
167			found: true,
168		},
169		{
170			name:   "not found",
171			thread: createTestThread(t),
172			setup:  func(*Post) PostID { return 42 },
173		},
174	}
175
176	for _, tc := range cases {
177		t.Run(tc.name, func(t *testing.T) {
178			replyID := tc.setup(tc.thread)
179
180			reply, found := tc.thread.GetReply(replyID)
181
182			uassert.Equal(t, tc.found, found)
183			if reply != nil {
184				uassert.Equal(t, uint(replyID), uint(reply.ID))
185			}
186		})
187	}
188}
189
190func TestThreadDeleteReply(t *testing.T) {
191	thread := createTestThread(t)
192	cases := []struct {
193		name  string
194		setup func() PostID
195		err   string
196	}{
197		{
198			name: "ok",
199			setup: func() PostID {
200				reply := thread.AddReply(testutils.TestAddress("replier"), "")
201				return reply.ID
202			},
203		},
204		{
205			name: "ok nested",
206			setup: func() PostID {
207				reply := thread.AddReply(testutils.TestAddress("replier"), "")
208				return reply.AddReply(testutils.TestAddress("replier2"), "").ID
209			},
210		},
211		{
212			name:  "invalid",
213			setup: func() PostID { return thread.ID },
214			err:   "expected an ID of an inner reply",
215		},
216		{
217			name:  "not found",
218			setup: func() PostID { return 42 },
219			err:   "reply not found in thread",
220		},
221	}
222
223	for _, tc := range cases {
224		t.Run(tc.name, func(t *testing.T) {
225			replyID := tc.setup()
226
227			err := thread.DeleteReply(replyID)
228
229			if tc.err != "" {
230				uassert.ErrorContains(t, err, tc.err)
231				return
232			}
233
234			uassert.NoError(t, err)
235			_, found := thread.GetReply(replyID)
236			uassert.False(t, found)
237		})
238	}
239}
240
241func TestThreadRenderSummary(t *testing.T) {
242	t.Skip("TODO: implement")
243}
244
245func TestThreadRender(t *testing.T) {
246	t.Skip("TODO: implement")
247}
248
249func TestThreadRenderInner(t *testing.T) {
250	t.Skip("TODO: implement")
251}
252
253func TestNewReply(t *testing.T) {
254	testing.SetRealm(testing.NewCodeRealm("gno.land/r/gnoland/boards2/v1"))
255
256	creator := testutils.TestAddress("creator")
257	body := strings.Repeat("A", 82)
258	boardID := BoardID(1)
259	threadID := PostID(42)
260	parentID := PostID(1)
261	replyID := PostID(2)
262	boardName := "test123"
263	perms := createBasicBoardPermissions(creator)
264	board := newBoard(boardID, boardName, creator, perms)
265	url := ufmt.Sprintf(
266		"/r/gnoland/boards2/v1:%s/%d/%d",
267		boardName,
268		uint(threadID),
269		uint(replyID),
270	)
271	replyURL := ufmt.Sprintf(
272		"/r/gnoland/boards2/v1$help&func=CreateReply&boardID=%d&body=&replyID=%d&threadID=%d",
273		uint(boardID),
274		uint(replyID),
275		uint(threadID),
276	)
277	deleteURL := ufmt.Sprintf(
278		"/r/gnoland/boards2/v1$help&func=DeleteReply&boardID=%d&replyID=%d&threadID=%d",
279		uint(boardID),
280		uint(replyID),
281		uint(threadID),
282	)
283
284	reply := newPost(board, threadID, replyID, creator, "", body)
285	reply.ParentID = parentID
286
287	uassert.False(t, reply.IsThread())
288	uassert.Equal(t, uint(replyID), uint(reply.ID))
289	uassert.False(t, reply.CreatedAt().IsZero())
290	uassert.True(t, reply.UpdatedAt.IsZero())
291	uassert.False(t, reply.HasReplies())
292	uassert.Equal(t, body[:77]+"...", reply.Summary())
293	uassert.Equal(t, url, makeReplyURI(reply))
294	uassert.Equal(t, replyURL, makeCreateReplyURI(reply))
295	uassert.Equal(t, deleteURL, makeDeletePostURI(reply))
296}
297
298func TestReplyAddReply(t *testing.T) {
299	replier := testutils.TestAddress("replier")
300	thread := createTestThread(t)
301	parentReply := thread.AddReply(testutils.TestAddress("parentReplier"), "")
302	parentReplyID := uint(parentReply.ID)
303	body := "A child reply"
304
305	reply := parentReply.AddReply(replier, body)
306
307	r, found := thread.GetReply(reply.ID)
308	uassert.True(t, found)
309	uassert.True(t, reply == r)
310	uassert.Equal(t, parentReplyID, uint(reply.ParentID))
311	uassert.Equal(t, parentReplyID+1, uint(reply.ID))
312	uassert.Equal(t, reply.Creator, replier)
313	uassert.Equal(t, reply.Body, body)
314	uassert.False(t, reply.HasReplies())
315	uassert.True(t, parentReply.HasReplies())
316}
317
318func TestReplyGetReply(t *testing.T) {
319	thread := createTestThread(t)
320	parentReply := thread.AddReply(testutils.TestAddress("parentReplier"), "")
321	cases := []struct {
322		name  string
323		setup func() PostID
324		found bool
325	}{
326		{
327			name: "found",
328			setup: func() PostID {
329				reply := parentReply.AddReply(testutils.TestAddress("replier"), "")
330				return reply.ID
331			},
332			found: true,
333		},
334		{
335			name:  "not found",
336			setup: func() PostID { return 42 },
337		},
338	}
339
340	for _, tc := range cases {
341		t.Run(tc.name, func(t *testing.T) {
342			replyID := tc.setup()
343
344			reply, found := thread.GetReply(replyID)
345
346			uassert.Equal(t, tc.found, found)
347			if reply != nil {
348				uassert.Equal(t, uint(replyID), uint(reply.ID))
349			}
350		})
351	}
352}
353
354func TestReplyDeleteReply(t *testing.T) {
355	thread := createTestThread(t)
356	parentReply := thread.AddReply(testutils.TestAddress("replier"), "")
357	reply := parentReply.AddReply(testutils.TestAddress("replier2"), "")
358
359	// NOTE: Deleting a reply from a parent reply should eventually be suported
360	uassert.PanicsWithMessage(t, "cannot delete reply from a non-thread post", func() {
361		parentReply.DeleteReply(reply.ID)
362	})
363}
364
365func TestReplyRender(t *testing.T) {
366	t.Skip("TODO: implement")
367}
368
369func createTestThread(t *testing.T) *Post {
370	t.Helper()
371
372	creator := testutils.TestAddress("creator")
373	perms := createBasicBoardPermissions(creator)
374	board := newBoard(1, "test_board_123", creator, perms)
375	return board.AddThread(creator, "Title", "Body")
376}
377
378func createTestReply(t *testing.T) *Post {
379	t.Helper()
380
381	creator := testutils.TestAddress("replier")
382	thread := createTestThread(t)
383	return thread.AddReply(creator, "Test message")
384}