First pass at adding comment trees. (#2362)
* First pass at adding comment trees. - Extracted comment replies into its own table. - Added ltree column to comment - Added parent_id param to GetComments to fetch a tree branch - No paging / limiting yet * Adding child_count to comment_aggregates. * Adding parent comment update counts * Fix unit tests. * Comment tree paging mostly done. * Fix clippy * Fix drone tests wrong postgres version. * Fix unit tests. * Add back in delete in unit test. * Add postgres upgrade script. * Fixing some PR comments. * Move update ltree into Comment::create * Updating based on comments. * Fix send soft fail.
This commit is contained in:
parent
becb8b4f66
commit
9c3efe32e7
72 changed files with 3692 additions and 2661 deletions
|
|
@ -155,7 +155,7 @@ steps:
|
|||
|
||||
services:
|
||||
- name: database
|
||||
image: postgres:12-alpine
|
||||
image: postgres:14-alpine
|
||||
environment:
|
||||
POSTGRES_USER: lemmy
|
||||
POSTGRES_PASSWORD: password
|
||||
|
|
|
|||
43
Cargo.lock
generated
43
Cargo.lock
generated
|
|
@ -834,12 +834,12 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "darling"
|
||||
version = "0.13.1"
|
||||
version = "0.13.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d0d720b8683f8dd83c65155f0530560cba68cd2bf395f6513a483caee57ff7f4"
|
||||
checksum = "a01d95850c592940db9b8194bc39f4bc0e89dee5c4265e4b1807c34a9aba453c"
|
||||
dependencies = [
|
||||
"darling_core 0.13.1",
|
||||
"darling_macro 0.13.1",
|
||||
"darling_core 0.13.4",
|
||||
"darling_macro 0.13.4",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -868,9 +868,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "darling_core"
|
||||
version = "0.13.1"
|
||||
version = "0.13.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7a340f241d2ceed1deb47ae36c4144b2707ec7dd0b649f894cb39bb595986324"
|
||||
checksum = "859d65a907b6852c9361e3185c862aae7fafd2887876799fa55f5f99dc40d610"
|
||||
dependencies = [
|
||||
"fnv",
|
||||
"ident_case",
|
||||
|
|
@ -907,11 +907,11 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "darling_macro"
|
||||
version = "0.13.1"
|
||||
version = "0.13.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "72c41b3b7352feb3211a0d743dc5700a4e3b60f51bd2b368892d1e0f9a95f44b"
|
||||
checksum = "9c972679f83bdf9c42bd905396b6c3588a843a17f0f16dfcfa3e2c5d57441835"
|
||||
dependencies = [
|
||||
"darling_core 0.13.1",
|
||||
"darling_core 0.13.4",
|
||||
"quote 1.0.18",
|
||||
"syn 1.0.96",
|
||||
]
|
||||
|
|
@ -1058,6 +1058,16 @@ dependencies = [
|
|||
"syn 1.0.96",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "diesel_ltree"
|
||||
version = "0.2.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "55a0b2b2e948a2d8ab673ccee9f37b20bdcc8b7acb40a242a0fdf53d4c2678b0"
|
||||
dependencies = [
|
||||
"byteorder",
|
||||
"diesel",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "diesel_migrations"
|
||||
version = "1.4.0"
|
||||
|
|
@ -1132,7 +1142,7 @@ name = "doku-derive"
|
|||
version = "0.11.0"
|
||||
source = "git+https://github.com/anixe/doku#10a0339a82be92b5f160aac325d11c9c2ef875e1"
|
||||
dependencies = [
|
||||
"darling 0.13.1",
|
||||
"darling 0.13.4",
|
||||
"proc-macro2 1.0.39",
|
||||
"quote 1.0.18",
|
||||
"syn 1.0.96",
|
||||
|
|
@ -1984,6 +1994,7 @@ dependencies = [
|
|||
"chrono",
|
||||
"diesel",
|
||||
"diesel-derive-newtype",
|
||||
"diesel_ltree",
|
||||
"diesel_migrations",
|
||||
"lemmy_utils",
|
||||
"once_cell",
|
||||
|
|
@ -2002,6 +2013,7 @@ name = "lemmy_db_views"
|
|||
version = "0.16.5"
|
||||
dependencies = [
|
||||
"diesel",
|
||||
"diesel_ltree",
|
||||
"lemmy_db_schema",
|
||||
"serde",
|
||||
"serial_test",
|
||||
|
|
@ -3507,22 +3519,21 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "serde_with"
|
||||
version = "1.12.0"
|
||||
version = "1.14.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ec1e6ec4d8950e5b1e894eac0d360742f3b1407a6078a604a731c4b3f49cefbc"
|
||||
checksum = "678b5a069e50bf00ecd22d0cd8ddf7c236f68581b03db652061ed5eb13a312ff"
|
||||
dependencies = [
|
||||
"rustversion",
|
||||
"serde",
|
||||
"serde_with_macros",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_with_macros"
|
||||
version = "1.5.1"
|
||||
version = "1.5.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "12e47be9471c72889ebafb5e14d5ff930d89ae7a67bbdb5f8abb564f845a927e"
|
||||
checksum = "e182d6ec6f05393cc0e5ed1bf81ad6db3a8feedf8ee515ecdd369809bcce8082"
|
||||
dependencies = [
|
||||
"darling 0.13.1",
|
||||
"darling 0.13.4",
|
||||
"proc-macro2 1.0.39",
|
||||
"quote 1.0.18",
|
||||
"syn 1.0.96",
|
||||
|
|
|
|||
|
|
@ -12,14 +12,17 @@
|
|||
"api-test": "jest -i follow.spec.ts && jest -i src/post.spec.ts && jest -i comment.spec.ts && jest -i private_message.spec.ts && jest -i user.spec.ts && jest -i community.spec.ts"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@sniptt/monads": "^0.5.10",
|
||||
"@types/jest": "^26.0.23",
|
||||
"eslint": "^7.30.0",
|
||||
"eslint-plugin-jane": "^9.0.3",
|
||||
"class-transformer": "^0.5.1",
|
||||
"eslint": "^8.20.0",
|
||||
"eslint-plugin-jane": "^11.2.2",
|
||||
"jest": "^27.0.6",
|
||||
"lemmy-js-client": "0.17.0-rc.11",
|
||||
"lemmy-js-client": "0.17.0-rc.37",
|
||||
"node-fetch": "^2.6.1",
|
||||
"prettier": "^2.3.2",
|
||||
"prettier": "^2.7.1",
|
||||
"reflect-metadata": "^0.1.13",
|
||||
"ts-jest": "^27.0.3",
|
||||
"typescript": "^4.3.5"
|
||||
"typescript": "^4.6.4"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,8 @@
|
|||
jest.setTimeout(180000);
|
||||
import {None, Some} from '@sniptt/monads';
|
||||
import { CommentView } from 'lemmy-js-client';
|
||||
import { PostResponse } from 'lemmy-js-client';
|
||||
|
||||
import {
|
||||
alpha,
|
||||
beta,
|
||||
|
|
@ -24,10 +28,9 @@ import {
|
|||
randomString,
|
||||
API,
|
||||
unfollows,
|
||||
getComments,
|
||||
getCommentParentId,
|
||||
} from './shared';
|
||||
import { CommentView } from 'lemmy-js-client';
|
||||
|
||||
import { PostResponse } from 'lemmy-js-client';
|
||||
|
||||
let postRes: PostResponse;
|
||||
|
||||
|
|
@ -39,7 +42,7 @@ beforeAll(async () => {
|
|||
let betaCommunity = (await resolveBetaCommunity(alpha)).community;
|
||||
postRes = await createPost(
|
||||
alpha,
|
||||
betaCommunity.community.id
|
||||
betaCommunity.unwrap().community.id
|
||||
);
|
||||
});
|
||||
|
||||
|
|
@ -62,14 +65,14 @@ function assertCommentFederation(
|
|||
}
|
||||
|
||||
test('Create a comment', async () => {
|
||||
let commentRes = await createComment(alpha, postRes.post_view.post.id);
|
||||
let commentRes = await createComment(alpha, postRes.post_view.post.id, None);
|
||||
expect(commentRes.comment_view.comment.content).toBeDefined();
|
||||
expect(commentRes.comment_view.community.local).toBe(false);
|
||||
expect(commentRes.comment_view.creator.local).toBe(true);
|
||||
expect(commentRes.comment_view.counts.score).toBe(1);
|
||||
|
||||
// Make sure that comment is liked on beta
|
||||
let betaComment = (await resolveComment(beta, commentRes.comment_view.comment)).comment;
|
||||
let betaComment = (await resolveComment(beta, commentRes.comment_view.comment)).comment.unwrap();
|
||||
expect(betaComment).toBeDefined();
|
||||
expect(betaComment.community.local).toBe(true);
|
||||
expect(betaComment.creator.local).toBe(false);
|
||||
|
|
@ -78,15 +81,15 @@ test('Create a comment', async () => {
|
|||
});
|
||||
|
||||
test('Create a comment in a non-existent post', async () => {
|
||||
let commentRes = await createComment(alpha, -1);
|
||||
expect(commentRes).toStrictEqual({ error: 'couldnt_find_post' });
|
||||
let commentRes = await createComment(alpha, -1, None) as any;
|
||||
expect(commentRes.error).toBe('couldnt_find_post');
|
||||
});
|
||||
|
||||
test('Update a comment', async () => {
|
||||
let commentRes = await createComment(alpha, postRes.post_view.post.id);
|
||||
let commentRes = await createComment(alpha, postRes.post_view.post.id, None);
|
||||
// Federate the comment first
|
||||
let betaComment = (await resolveComment(beta, commentRes.comment_view.comment)).comment;
|
||||
assertCommentFederation(betaComment, commentRes.comment_view);
|
||||
assertCommentFederation(betaComment.unwrap(), commentRes.comment_view);
|
||||
|
||||
let updateCommentRes = await editComment(
|
||||
alpha,
|
||||
|
|
@ -102,7 +105,7 @@ test('Update a comment', async () => {
|
|||
let betaCommentUpdated = (await resolveComment(
|
||||
beta,
|
||||
commentRes.comment_view.comment
|
||||
)).comment;
|
||||
)).comment.unwrap();
|
||||
assertCommentFederation(
|
||||
betaCommentUpdated,
|
||||
updateCommentRes.comment_view
|
||||
|
|
@ -110,7 +113,7 @@ test('Update a comment', async () => {
|
|||
});
|
||||
|
||||
test('Delete a comment', async () => {
|
||||
let commentRes = await createComment(alpha, postRes.post_view.post.id);
|
||||
let commentRes = await createComment(alpha, postRes.post_view.post.id, None);
|
||||
|
||||
let deleteCommentRes = await deleteComment(
|
||||
alpha,
|
||||
|
|
@ -121,8 +124,8 @@ test('Delete a comment', async () => {
|
|||
expect(deleteCommentRes.comment_view.comment.content).toBe("");
|
||||
|
||||
// Make sure that comment is undefined on beta
|
||||
let betaCommentRes: any = await resolveComment(beta, commentRes.comment_view.comment);
|
||||
expect(betaCommentRes).toStrictEqual({ error: 'couldnt_find_object' });
|
||||
let betaCommentRes = await resolveComment(beta, commentRes.comment_view.comment) as any;
|
||||
expect(betaCommentRes.error).toBe('couldnt_find_object');
|
||||
|
||||
let undeleteCommentRes = await deleteComment(
|
||||
alpha,
|
||||
|
|
@ -132,7 +135,7 @@ test('Delete a comment', async () => {
|
|||
expect(undeleteCommentRes.comment_view.comment.deleted).toBe(false);
|
||||
|
||||
// Make sure that comment is undeleted on beta
|
||||
let betaComment2 = (await resolveComment(beta, commentRes.comment_view.comment)).comment;
|
||||
let betaComment2 = (await resolveComment(beta, commentRes.comment_view.comment)).comment.unwrap();
|
||||
expect(betaComment2.comment.deleted).toBe(false);
|
||||
assertCommentFederation(
|
||||
betaComment2,
|
||||
|
|
@ -141,12 +144,12 @@ test('Delete a comment', async () => {
|
|||
});
|
||||
|
||||
test('Remove a comment from admin and community on the same instance', async () => {
|
||||
let commentRes = await createComment(alpha, postRes.post_view.post.id);
|
||||
let commentRes = await createComment(alpha, postRes.post_view.post.id, None);
|
||||
|
||||
// Get the id for beta
|
||||
let betaCommentId = (
|
||||
await resolveComment(beta, commentRes.comment_view.comment)
|
||||
).comment.comment.id;
|
||||
).comment.unwrap().comment.id;
|
||||
|
||||
// The beta admin removes it (the community lives on beta)
|
||||
let removeCommentRes = await removeComment(beta, true, betaCommentId);
|
||||
|
|
@ -154,17 +157,17 @@ test('Remove a comment from admin and community on the same instance', async ()
|
|||
expect(removeCommentRes.comment_view.comment.content).toBe("");
|
||||
|
||||
// Make sure that comment is removed on alpha (it gets pushed since an admin from beta removed it)
|
||||
let refetchedPost = await getPost(alpha, postRes.post_view.post.id);
|
||||
expect(refetchedPost.comments[0].comment.removed).toBe(true);
|
||||
let refetchedPostComments = await getComments(alpha, postRes.post_view.post.id);
|
||||
expect(refetchedPostComments.comments[0].comment.removed).toBe(true);
|
||||
|
||||
let unremoveCommentRes = await removeComment(beta, false, betaCommentId);
|
||||
expect(unremoveCommentRes.comment_view.comment.removed).toBe(false);
|
||||
|
||||
// Make sure that comment is unremoved on beta
|
||||
let refetchedPost2 = await getPost(alpha, postRes.post_view.post.id);
|
||||
expect(refetchedPost2.comments[0].comment.removed).toBe(false);
|
||||
let refetchedPostComments2 = await getComments(alpha, postRes.post_view.post.id);
|
||||
expect(refetchedPostComments2.comments[0].comment.removed).toBe(false);
|
||||
assertCommentFederation(
|
||||
refetchedPost2.comments[0],
|
||||
refetchedPostComments2.comments[0],
|
||||
unremoveCommentRes.comment_view
|
||||