]> Untitled Git - lemmy.git/blob - api_tests/src/comment.spec.ts
19c2797b2872d8725c5d4a6b2bfac367575363e1
[lemmy.git] / api_tests / src / comment.spec.ts
1 jest.setTimeout(180000);
2
3 import { PostResponse } from "lemmy-js-client/dist/types/PostResponse";
4 import {
5   alpha,
6   beta,
7   gamma,
8   setupLogins,
9   createPost,
10   getPost,
11   resolveComment,
12   likeComment,
13   followBeta,
14   resolveBetaCommunity,
15   createComment,
16   editComment,
17   deleteComment,
18   removeComment,
19   getMentions,
20   resolvePost,
21   unfollowRemotes,
22   createCommunity,
23   registerUser,
24   reportComment,
25   listCommentReports,
26   randomString,
27   API,
28   unfollows,
29   getComments,
30   getCommentParentId,
31   resolveCommunity,
32   getPersonDetails,
33 } from "./shared";
34 import { CommentView } from "lemmy-js-client/dist/types/CommentView";
35
36 let postRes: PostResponse;
37
38 beforeAll(async () => {
39   await setupLogins();
40   await unfollows();
41   await followBeta(alpha);
42   await followBeta(gamma);
43   let betaCommunity = (await resolveBetaCommunity(alpha)).community;
44   if (betaCommunity) {
45     postRes = await createPost(alpha, betaCommunity.community.id);
46   }
47 });
48
49 afterAll(async () => {
50   await unfollows();
51 });
52
53 function assertCommentFederation(
54   commentOne?: CommentView,
55   commentTwo?: CommentView,
56 ) {
57   expect(commentOne?.comment.ap_id).toBe(commentTwo?.comment.ap_id);
58   expect(commentOne?.comment.content).toBe(commentTwo?.comment.content);
59   expect(commentOne?.creator.name).toBe(commentTwo?.creator.name);
60   expect(commentOne?.community.actor_id).toBe(commentTwo?.community.actor_id);
61   expect(commentOne?.comment.published).toBe(commentTwo?.comment.published);
62   expect(commentOne?.comment.updated).toBe(commentOne?.comment.updated);
63   expect(commentOne?.comment.deleted).toBe(commentOne?.comment.deleted);
64   expect(commentOne?.comment.removed).toBe(commentOne?.comment.removed);
65 }
66
67 test("Create a comment", async () => {
68   let commentRes = await createComment(alpha, postRes.post_view.post.id);
69   expect(commentRes.comment_view.comment.content).toBeDefined();
70   expect(commentRes.comment_view.community.local).toBe(false);
71   expect(commentRes.comment_view.creator.local).toBe(true);
72   expect(commentRes.comment_view.counts.score).toBe(1);
73
74   // Make sure that comment is liked on beta
75   let betaComment = (
76     await resolveComment(beta, commentRes.comment_view.comment)
77   ).comment;
78   expect(betaComment).toBeDefined();
79   expect(betaComment?.community.local).toBe(true);
80   expect(betaComment?.creator.local).toBe(false);
81   expect(betaComment?.counts.score).toBe(1);
82   assertCommentFederation(betaComment, commentRes.comment_view);
83 });
84
85 test("Create a comment in a non-existent post", async () => {
86   await expect(createComment(alpha, -1)).rejects.toBe("couldnt_find_post");
87 });
88
89 test("Update a comment", async () => {
90   let commentRes = await createComment(alpha, postRes.post_view.post.id);
91   // Federate the comment first
92   let betaComment = (
93     await resolveComment(beta, commentRes.comment_view.comment)
94   ).comment;
95   assertCommentFederation(betaComment, commentRes.comment_view);
96
97   let updateCommentRes = await editComment(
98     alpha,
99     commentRes.comment_view.comment.id,
100   );
101   expect(updateCommentRes.comment_view.comment.content).toBe(
102     "A jest test federated comment update",
103   );
104   expect(updateCommentRes.comment_view.community.local).toBe(false);
105   expect(updateCommentRes.comment_view.creator.local).toBe(true);
106
107   // Make sure that post is updated on beta
108   let betaCommentUpdated = (
109     await resolveComment(beta, commentRes.comment_view.comment)
110   ).comment;
111   assertCommentFederation(betaCommentUpdated, updateCommentRes.comment_view);
112 });
113
114 test("Delete a comment", async () => {
115   let commentRes = await createComment(alpha, postRes.post_view.post.id);
116
117   let deleteCommentRes = await deleteComment(
118     alpha,
119     true,
120     commentRes.comment_view.comment.id,
121   );
122   expect(deleteCommentRes.comment_view.comment.deleted).toBe(true);
123
124   // Make sure that comment is undefined on beta
125   await expect(
126     resolveComment(beta, commentRes.comment_view.comment),
127   ).rejects.toBe("couldnt_find_object");
128
129   let undeleteCommentRes = await deleteComment(
130     alpha,
131     false,
132     commentRes.comment_view.comment.id,
133   );
134   expect(undeleteCommentRes.comment_view.comment.deleted).toBe(false);
135
136   // Make sure that comment is undeleted on beta
137   let betaComment2 = (
138     await resolveComment(beta, commentRes.comment_view.comment)
139   ).comment;
140   expect(betaComment2?.comment.deleted).toBe(false);
141   assertCommentFederation(betaComment2, undeleteCommentRes.comment_view);
142 });
143
144 test.skip("Remove a comment from admin and community on the same instance", async () => {
145   let commentRes = await createComment(alpha, postRes.post_view.post.id);
146
147   // Get the id for beta
148   let betaCommentId = (
149     await resolveComment(beta, commentRes.comment_view.comment)
150   ).comment?.comment.id;
151
152   if (!betaCommentId) {
153     throw "beta comment id is missing";
154   }
155
156   // The beta admin removes it (the community lives on beta)
157   let removeCommentRes = await removeComment(beta, true, betaCommentId);
158   expect(removeCommentRes.comment_view.comment.removed).toBe(true);
159
160   // Make sure that comment is removed on alpha (it gets pushed since an admin from beta removed it)
161   let refetchedPostComments = await getPersonDetails(
162     alpha,
163     commentRes.comment_view.comment.creator_id,
164   );
165   expect(refetchedPostComments.comments[0].comment.removed).toBe(true);
166
167   let unremoveCommentRes = await removeComment(beta, false, betaCommentId);
168   expect(unremoveCommentRes.comment_view.comment.removed).toBe(false);
169
170   // Make sure that comment is unremoved on beta
171   let refetchedPostComments2 = await getComments(
172     alpha,
173     postRes.post_view.post.id,
174   );
175   expect(refetchedPostComments2.comments[0].comment.removed).toBe(false);
176   assertCommentFederation(
177     refetchedPostComments2.comments[0],
178     unremoveCommentRes.comment_view,
179   );
180 });
181
182 test("Remove a comment from admin and community on different instance", async () => {
183   let alpha_user = await registerUser(alpha);
184   let newAlphaApi: API = {
185     client: alpha.client,
186     auth: alpha_user.jwt ?? "",
187   };
188
189   // New alpha user creates a community, post, and comment.
190   let newCommunity = await createCommunity(newAlphaApi);
191   let newPost = await createPost(
192     newAlphaApi,
193     newCommunity.community_view.community.id,
194   );
195   let commentRes = await createComment(newAlphaApi, newPost.post_view.post.id);
196   expect(commentRes.comment_view.comment.content).toBeDefined();
197
198   // Beta searches that to cache it, then removes it
199   let betaComment = (
200     await resolveComment(beta, commentRes.comment_view.comment)
201   ).comment;
202
203   if (!betaComment) {
204     throw "beta comment missing";
205   }
206
207   let removeCommentRes = await removeComment(
208     beta,
209     true,
210     betaComment.comment.id,
211   );
212   expect(removeCommentRes.comment_view.comment.removed).toBe(true);
213
214   // Make sure its not removed on alpha
215   let refetchedPostComments = await getComments(
216     alpha,
217     newPost.post_view.post.id,
218   );
219   expect(refetchedPostComments.comments[0].comment.removed).toBe(false);
220   assertCommentFederation(
221     refetchedPostComments.comments[0],
222     commentRes.comment_view,
223   );
224 });
225
226 test("Unlike a comment", async () => {
227   let commentRes = await createComment(alpha, postRes.post_view.post.id);
228   let unlike = await likeComment(alpha, 0, commentRes.comment_view.comment);
229   expect(unlike.comment_view.counts.score).toBe(0);
230
231   // Make sure that post is unliked on beta
232   let betaComment = (
233     await resolveComment(beta, commentRes.comment_view.comment)
234   ).comment;
235   expect(betaComment).toBeDefined();
236   expect(betaComment?.community.local).toBe(true);
237   expect(betaComment?.creator.local).toBe(false);
238   expect(betaComment?.counts.score).toBe(0);
239 });
240
241 test("Federated comment like", async () => {
242   let commentRes = await createComment(alpha, postRes.post_view.post.id);
243
244   // Find the comment on beta
245   let betaComment = (
246     await resolveComment(beta, commentRes.comment_view.comment)
247   ).comment;
248
249   if (!betaComment) {
250     throw "Missing beta comment";
251   }
252
253   let like = await likeComment(beta, 1, betaComment.comment);
254   expect(like.comment_view.counts.score).toBe(2);
255
256   // Get the post from alpha, check the likes
257   let postComments = await getComments(alpha, postRes.post_view.post.id);
258   expect(postComments.comments[0].counts.score).toBe(2);
259 });
260
261 test("Reply to a comment", async () => {
262   // Create a comment on alpha, find it on beta
263   let commentRes = await createComment(alpha, postRes.post_view.post.id);
264   let betaComment = (
265     await resolveComment(beta, commentRes.comment_view.comment)
266   ).comment;
267
268   if (!betaComment) {
269     throw "Missing beta comment";
270   }
271
272   // find that comment id on beta
273
274   // Reply from beta
275   let replyRes = await createComment(
276     beta,
277     betaComment.post.id,
278     betaComment.comment.id,
279   );
280   expect(replyRes.comment_view.comment.content).toBeDefined();
281   expect(replyRes.comment_view.community.local).toBe(true);
282   expect(replyRes.comment_view.creator.local).toBe(true);
283   expect(getCommentParentId(replyRes.comment_view.comment)).toBe(
284     betaComment.comment.id,
285   );
286   expect(replyRes.comment_view.counts.score).toBe(1);
287
288   // Make sure that comment is seen on alpha
289   // TODO not sure why, but a searchComment back to alpha, for the ap_id of betas
290   // comment, isn't working.
291   // let searchAlpha = await searchComment(alpha, replyRes.comment);
292   let postComments = await getComments(alpha, postRes.post_view.post.id);
293   let alphaComment = postComments.comments[0];
294   expect(alphaComment.comment.content).toBeDefined();
295   expect(getCommentParentId(alphaComment.comment)).toBe(
296     postComments.comments[1].comment.id,
297   );
298   expect(alphaComment.community.local).toBe(false);
299   expect(alphaComment.creator.local).toBe(false);
300   expect(alphaComment.counts.score).toBe(1);
301   assertCommentFederation(alphaComment, replyRes.comment_view);
302 });
303
304 test("Mention beta", async () => {
305   // Create a mention on alpha
306   let mentionContent = "A test mention of @lemmy_beta@lemmy-beta:8551";
307   let commentRes = await createComment(alpha, postRes.post_view.post.id);
308   let mentionRes = await createComment(
309     alpha,
310     postRes.post_view.post.id,
311     commentRes.comment_view.comment.id,
312     mentionContent,
313   );
314   expect(mentionRes.comment_view.comment.content).toBeDefined();
315   expect(mentionRes.comment_view.community.local).toBe(false);
316   expect(mentionRes.comment_view.creator.local).toBe(true);
317   expect(mentionRes.comment_view.counts.score).toBe(1);
318
319   let mentionsRes = await getMentions(beta);
320   expect(mentionsRes.mentions[0].comment.content).toBeDefined();
321   expect(mentionsRes.mentions[0].community.local).toBe(true);
322   expect(mentionsRes.mentions[0].creator.local).toBe(false);
323   expect(mentionsRes.mentions[0].counts.score).toBe(1);
324 });
325
326 test("Comment Search", async () => {
327   let commentRes = await createComment(alpha, postRes.post_view.post.id);
328   let betaComment = (
329     await resolveComment(beta, commentRes.comment_view.comment)
330   ).comment;
331   assertCommentFederation(betaComment, commentRes.comment_view);
332 });
333
334 test("A and G subscribe to B (center) A posts, G mentions B, it gets announced to A", async () => {
335   // Create a local post
336   let alphaCommunity = (await resolveCommunity(alpha, "!main@lemmy-alpha:8541"))
337     .community;
338
339   if (!alphaCommunity) {
340     throw "Missing alpha community";
341   }
342
343   let alphaPost = await createPost(alpha, alphaCommunity.community.id);
344   expect(alphaPost.post_view.community.local).toBe(true);
345
346   // Make sure gamma sees it
347   let gammaPost = (await resolvePost(gamma, alphaPost.post_view.post)).post;
348
349   if (!gammaPost) {
350     throw "Missing gamma post";
351   }
352
353   let commentContent =
354     "A jest test federated comment announce, lets mention @lemmy_beta@lemmy-beta:8551";
355   let commentRes = await createComment(
356     gamma,
357     gammaPost.post.id,
358     undefined,
359     commentContent,
360   );
361   expect(commentRes.comment_view.comment.content).toBe(commentContent);
362   expect(commentRes.comment_view.community.local).toBe(false);
363   expect(commentRes.comment_view.creator.local).toBe(true);
364   expect(commentRes.comment_view.counts.score).toBe(1);
365
366   // Make sure alpha sees it
367   let alphaPostComments2 = await getComments(
368     alpha,
369     alphaPost.post_view.post.id,
370   );
371   expect(alphaPostComments2.comments[0].comment.content).toBe(commentContent);
372   expect(alphaPostComments2.comments[0].community.local).toBe(true);
373   expect(alphaPostComments2.comments[0].creator.local).toBe(false);
374   expect(alphaPostComments2.comments[0].counts.score).toBe(1);
375   assertCommentFederation(
376     alphaPostComments2.comments[0],
377     commentRes.comment_view,
378   );
379
380   // Make sure beta has mentions
381   let mentionsRes = await getMentions(beta);
382   expect(mentionsRes.mentions[0].comment.content).toBe(commentContent);
383   expect(mentionsRes.mentions[0].community.local).toBe(false);
384   expect(mentionsRes.mentions[0].creator.local).toBe(false);
385   // TODO this is failing because fetchInReplyTos aren't getting score
386   // expect(mentionsRes.mentions[0].score).toBe(1);
387 });
388
389 test("Check that activity from another instance is sent to third instance", async () => {
390   // Alpha and gamma users follow beta community
391   let alphaFollow = await followBeta(alpha);
392   expect(alphaFollow.community_view.community.local).toBe(false);
393   expect(alphaFollow.community_view.community.name).toBe("main");
394
395   let gammaFollow = await followBeta(gamma);
396   expect(gammaFollow.community_view.community.local).toBe(false);
397   expect(gammaFollow.community_view.community.name).toBe("main");
398
399   // Create a post on beta
400   let betaPost = await createPost(beta, 2);
401   expect(betaPost.post_view.community.local).toBe(true);
402
403   // Make sure gamma and alpha see it
404   let gammaPost = (await resolvePost(gamma, betaPost.post_view.post)).post;
405   if (!gammaPost) {
406     throw "Missing gamma post";
407   }
408   expect(gammaPost.post).toBeDefined();
409
410   let alphaPost = (await resolvePost(alpha, betaPost.post_view.post)).post;
411   if (!alphaPost) {
412     throw "Missing alpha post";
413   }
414   expect(alphaPost.post).toBeDefined();
415
416   // The bug: gamma comments, and alpha should see it.
417   let commentContent = "Comment from gamma";
418   let commentRes = await createComment(
419     gamma,
420     gammaPost.post.id,
421     undefined,
422     commentContent,
423   );
424   expect(commentRes.comment_view.comment.content).toBe(commentContent);
425   expect(commentRes.comment_view.community.local).toBe(false);
426   expect(commentRes.comment_view.creator.local).toBe(true);
427   expect(commentRes.comment_view.counts.score).toBe(1);
428
429   // Make sure alpha sees it
430   let alphaPostComments2 = await getComments(alpha, alphaPost.post.id);
431   expect(alphaPostComments2.comments[0].comment.content).toBe(commentContent);
432   expect(alphaPostComments2.comments[0].community.local).toBe(false);
433   expect(alphaPostComments2.comments[0].creator.local).toBe(false);
434   expect(alphaPostComments2.comments[0].counts.score).toBe(1);
435   assertCommentFederation(
436     alphaPostComments2.comments[0],
437     commentRes.comment_view,
438   );
439
440   await unfollowRemotes(alpha);
441   await unfollowRemotes(gamma);
442 });
443
444 test("Fetch in_reply_tos: A is unsubbed from B, B makes a post, and some embedded comments, A subs to B, B updates the lowest level comment, A fetches both the post and all the inreplyto comments for that post.", async () => {
445   // Unfollow all remote communities
446   let site = await unfollowRemotes(alpha);
447   expect(
448     site.my_user?.follows.filter(c => c.community.local == false).length,
449   ).toBe(0);
450
451   // B creates a post, and two comments, should be invisible to A
452   let postRes = await createPost(beta, 2);
453   expect(postRes.post_view.post.name).toBeDefined();
454
455   let parentCommentContent = "An invisible top level comment from beta";
456   let parentCommentRes = await createComment(
457     beta,
458     postRes.post_view.post.id,
459     undefined,
460     parentCommentContent,
461   );
462   expect(parentCommentRes.comment_view.comment.content).toBe(
463     parentCommentContent,
464   );
465
466   // B creates a comment, then a child one of that.
467   let childCommentContent = "An invisible child comment from beta";
468   let childCommentRes = await createComment(
469     beta,
470     postRes.post_view.post.id,
471     parentCommentRes.comment_view.comment.id,
472     childCommentContent,
473   );
474   expect(childCommentRes.comment_view.comment.content).toBe(
475     childCommentContent,
476   );
477
478   // Follow beta again
479   let follow = await followBeta(alpha);
480   expect(follow.community_view.community.local).toBe(false);
481   expect(follow.community_view.community.name).toBe("main");
482
483   // An update to the child comment on beta, should push the post, parent, and child to alpha now
484   let updatedCommentContent = "An update child comment from beta";
485   let updateRes = await editComment(
486     beta,
487     childCommentRes.comment_view.comment.id,
488     updatedCommentContent,
489   );
490   expect(updateRes.comment_view.comment.content).toBe(updatedCommentContent);
491
492   // Get the post from alpha
493   let alphaPostB = (await resolvePost(alpha, postRes.post_view.post)).post;
494   if (!alphaPostB) {
495     throw "Missing alpha post B";
496   }
497
498   let alphaPost = await getPost(alpha, alphaPostB.post.id);
499   let alphaPostComments = await getComments(alpha, alphaPostB.post.id);
500   expect(alphaPost.post_view.post.name).toBeDefined();
501   assertCommentFederation(
502     alphaPostComments.comments[1],
503     parentCommentRes.comment_view,
504   );
505   assertCommentFederation(
506     alphaPostComments.comments[0],
507     updateRes.comment_view,
508   );
509   expect(alphaPost.post_view.community.local).toBe(false);
510   expect(alphaPost.post_view.creator.local).toBe(false);
511
512   await unfollowRemotes(alpha);
513 });
514
515 test("Report a comment", async () => {
516   let betaCommunity = (await resolveBetaCommunity(beta)).community;
517   if (!betaCommunity) {
518     throw "Missing beta community";
519   }
520   let postRes = (await createPost(beta, betaCommunity.community.id)).post_view
521     .post;
522   expect(postRes).toBeDefined();
523   let commentRes = (await createComment(beta, postRes.id)).comment_view.comment;
524   expect(commentRes).toBeDefined();
525
526   let alphaComment = (await resolveComment(alpha, commentRes)).comment?.comment;
527   if (!alphaComment) {
528     throw "Missing alpha comment";
529   }
530
531   let alphaReport = (
532     await reportComment(alpha, alphaComment.id, randomString(10))
533   ).comment_report_view.comment_report;
534
535   let betaReport = (await listCommentReports(beta)).comment_reports[0]
536     .comment_report;
537   expect(betaReport).toBeDefined();
538   expect(betaReport.resolved).toBe(false);
539   expect(betaReport.original_comment_text).toBe(
540     alphaReport.original_comment_text,
541   );
542   expect(betaReport.reason).toBe(alphaReport.reason);
543 });