diff options
author | Julien Maulny <julien.maulny@protonmail.com> | 2019-11-15 19:05:08 +0100 |
---|---|---|
committer | Chocobozzz <chocobozzz@cpy.re> | 2019-12-04 09:36:45 +0100 |
commit | 69222afac8f8c41d90295b33f0695bbff352851e (patch) | |
tree | 63fe1faea94dd3bfc54e633631eecb275c969e54 /server | |
parent | 69c7f7525ddf13b7ced787d8b72ac74b43665517 (diff) | |
download | PeerTube-69222afac8f8c41d90295b33f0695bbff352851e.tar.gz PeerTube-69222afac8f8c41d90295b33f0695bbff352851e.tar.zst PeerTube-69222afac8f8c41d90295b33f0695bbff352851e.zip |
Soft delete video comments instead of detroy
Diffstat (limited to 'server')
-rw-r--r-- | server/controllers/activitypub/client.ts | 13 | ||||
-rw-r--r-- | server/controllers/api/videos/comment.ts | 12 | ||||
-rw-r--r-- | server/initializers/migrations/0450-soft-delete-video-comments.ts | 36 | ||||
-rw-r--r-- | server/lib/activitypub/process/process-delete.ts | 7 | ||||
-rw-r--r-- | server/lib/video-comment.ts | 9 | ||||
-rw-r--r-- | server/models/account/account.ts | 2 | ||||
-rw-r--r-- | server/models/video/video-comment.ts | 33 | ||||
-rw-r--r-- | server/tests/api/videos/multiple-servers.ts | 56 | ||||
-rw-r--r-- | server/tests/api/videos/video-comments.ts | 24 |
9 files changed, 162 insertions, 30 deletions
diff --git a/server/controllers/activitypub/client.ts b/server/controllers/activitypub/client.ts index 453ced8bf..5ed0435ff 100644 --- a/server/controllers/activitypub/client.ts +++ b/server/controllers/activitypub/client.ts | |||
@@ -308,13 +308,16 @@ async function videoCommentController (req: express.Request, res: express.Respon | |||
308 | 308 | ||
309 | const threadParentComments = await VideoCommentModel.listThreadParentComments(videoComment, undefined) | 309 | const threadParentComments = await VideoCommentModel.listThreadParentComments(videoComment, undefined) |
310 | const isPublic = true // Comments are always public | 310 | const isPublic = true // Comments are always public |
311 | const audience = getAudience(videoComment.Account.Actor, isPublic) | 311 | let videoCommentObject = videoComment.toActivityPubObject(threadParentComments) |
312 | 312 | ||
313 | const videoCommentObject = audiencify(videoComment.toActivityPubObject(threadParentComments), audience) | 313 | if (videoComment.Account) { |
314 | const audience = getAudience(videoComment.Account.Actor, isPublic) | ||
315 | videoCommentObject = audiencify(videoCommentObject, audience) | ||
314 | 316 | ||
315 | if (req.path.endsWith('/activity')) { | 317 | if (req.path.endsWith('/activity')) { |
316 | const data = buildCreateActivity(videoComment.url, videoComment.Account.Actor, videoCommentObject, audience) | 318 | const data = buildCreateActivity(videoComment.url, videoComment.Account.Actor, videoCommentObject, audience) |
317 | return activityPubResponse(activityPubContextify(data), res) | 319 | return activityPubResponse(activityPubContextify(data), res) |
320 | } | ||
318 | } | 321 | } |
319 | 322 | ||
320 | return activityPubResponse(activityPubContextify(videoCommentObject), res) | 323 | return activityPubResponse(activityPubContextify(videoCommentObject), res) |
diff --git a/server/controllers/api/videos/comment.ts b/server/controllers/api/videos/comment.ts index b2b06b170..5f3fed5c0 100644 --- a/server/controllers/api/videos/comment.ts +++ b/server/controllers/api/videos/comment.ts | |||
@@ -1,10 +1,11 @@ | |||
1 | import * as express from 'express' | 1 | import * as express from 'express' |
2 | import { cloneDeep } from 'lodash' | ||
2 | import { ResultList } from '../../../../shared/models' | 3 | import { ResultList } from '../../../../shared/models' |
3 | import { VideoCommentCreate } from '../../../../shared/models/videos/video-comment.model' | 4 | import { VideoCommentCreate } from '../../../../shared/models/videos/video-comment.model' |
4 | import { logger } from '../../../helpers/logger' | 5 | import { logger } from '../../../helpers/logger' |
5 | import { getFormattedObjects } from '../../../helpers/utils' | 6 | import { getFormattedObjects } from '../../../helpers/utils' |
6 | import { sequelizeTypescript } from '../../../initializers' | 7 | import { sequelizeTypescript } from '../../../initializers' |
7 | import { buildFormattedCommentTree, createVideoComment } from '../../../lib/video-comment' | 8 | import { buildFormattedCommentTree, createVideoComment, markCommentAsDeleted } from '../../../lib/video-comment' |
8 | import { | 9 | import { |
9 | asyncMiddleware, | 10 | asyncMiddleware, |
10 | asyncRetryTransactionMiddleware, | 11 | asyncRetryTransactionMiddleware, |
@@ -177,19 +178,22 @@ async function addVideoCommentReply (req: express.Request, res: express.Response | |||
177 | 178 | ||
178 | async function removeVideoComment (req: express.Request, res: express.Response) { | 179 | async function removeVideoComment (req: express.Request, res: express.Response) { |
179 | const videoCommentInstance = res.locals.videoCommentFull | 180 | const videoCommentInstance = res.locals.videoCommentFull |
181 | const videoCommentInstanceBefore = cloneDeep(videoCommentInstance) | ||
180 | 182 | ||
181 | await sequelizeTypescript.transaction(async t => { | 183 | await sequelizeTypescript.transaction(async t => { |
182 | await videoCommentInstance.destroy({ transaction: t }) | ||
183 | |||
184 | if (videoCommentInstance.isOwned() || videoCommentInstance.Video.isOwned()) { | 184 | if (videoCommentInstance.isOwned() || videoCommentInstance.Video.isOwned()) { |
185 | await sendDeleteVideoComment(videoCommentInstance, t) | 185 | await sendDeleteVideoComment(videoCommentInstance, t) |
186 | } | 186 | } |
187 | |||
188 | markCommentAsDeleted(videoCommentInstance) | ||
189 | |||
190 | await videoCommentInstance.save() | ||
187 | }) | 191 | }) |
188 | 192 | ||
189 | auditLogger.delete(getAuditIdFromRes(res), new CommentAuditView(videoCommentInstance.toFormattedJSON())) | 193 | auditLogger.delete(getAuditIdFromRes(res), new CommentAuditView(videoCommentInstance.toFormattedJSON())) |
190 | logger.info('Video comment %d deleted.', videoCommentInstance.id) | 194 | logger.info('Video comment %d deleted.', videoCommentInstance.id) |
191 | 195 | ||
192 | Hooks.runAction('action:api.video-comment.deleted', { comment: videoCommentInstance }) | 196 | Hooks.runAction('action:api.video-comment.deleted', { comment: videoCommentInstanceBefore }) |
193 | 197 | ||
194 | return res.type('json').status(204).end() | 198 | return res.type('json').status(204).end() |
195 | } | 199 | } |
diff --git a/server/initializers/migrations/0450-soft-delete-video-comments.ts b/server/initializers/migrations/0450-soft-delete-video-comments.ts new file mode 100644 index 000000000..bcfb97b56 --- /dev/null +++ b/server/initializers/migrations/0450-soft-delete-video-comments.ts | |||
@@ -0,0 +1,36 @@ | |||
1 | import * as Sequelize from 'sequelize' | ||
2 | |||
3 | async function up (utils: { | ||
4 | transaction: Sequelize.Transaction, | ||
5 | queryInterface: Sequelize.QueryInterface, | ||
6 | sequelize: Sequelize.Sequelize, | ||
7 | db: any | ||
8 | }): Promise<void> { | ||
9 | { | ||
10 | const data = { | ||
11 | type: Sequelize.INTEGER, | ||
12 | allowNull: true, | ||
13 | defaultValue: null | ||
14 | } | ||
15 | |||
16 | await utils.queryInterface.changeColumn('videoComment', 'accountId', data) | ||
17 | } | ||
18 | |||
19 | { | ||
20 | const data = { | ||
21 | type: Sequelize.DATE, | ||
22 | allowNull: true, | ||
23 | defaultValue: null | ||
24 | } | ||
25 | await utils.queryInterface.addColumn('videoComment', 'deletedAt', data) | ||
26 | } | ||
27 | } | ||
28 | |||
29 | function down (options) { | ||
30 | throw new Error('Not implemented.') | ||
31 | } | ||
32 | |||
33 | export { | ||
34 | up, | ||
35 | down | ||
36 | } | ||
diff --git a/server/lib/activitypub/process/process-delete.ts b/server/lib/activitypub/process/process-delete.ts index 79d0e0d79..e76132f91 100644 --- a/server/lib/activitypub/process/process-delete.ts +++ b/server/lib/activitypub/process/process-delete.ts | |||
@@ -5,6 +5,7 @@ import { sequelizeTypescript } from '../../../initializers' | |||
5 | import { ActorModel } from '../../../models/activitypub/actor' | 5 | import { ActorModel } from '../../../models/activitypub/actor' |
6 | import { VideoModel } from '../../../models/video/video' | 6 | import { VideoModel } from '../../../models/video/video' |
7 | import { VideoCommentModel } from '../../../models/video/video-comment' | 7 | import { VideoCommentModel } from '../../../models/video/video-comment' |
8 | import { markCommentAsDeleted } from '../../video-comment' | ||
8 | import { forwardVideoRelatedActivity } from '../send/utils' | 9 | import { forwardVideoRelatedActivity } from '../send/utils' |
9 | import { VideoPlaylistModel } from '../../../models/video/video-playlist' | 10 | import { VideoPlaylistModel } from '../../../models/video/video-playlist' |
10 | import { APProcessorOptions } from '../../../typings/activitypub-processor.model' | 11 | import { APProcessorOptions } from '../../../typings/activitypub-processor.model' |
@@ -128,7 +129,11 @@ function processDeleteVideoComment (byActor: MActorSignature, videoComment: Vide | |||
128 | throw new Error(`Account ${byActor.url} does not own video comment ${videoComment.url} or video ${videoComment.Video.url}`) | 129 | throw new Error(`Account ${byActor.url} does not own video comment ${videoComment.url} or video ${videoComment.Video.url}`) |
129 | } | 130 | } |
130 | 131 | ||
131 | await videoComment.destroy({ transaction: t }) | 132 | await sequelizeTypescript.transaction(async t => { |
133 | markCommentAsDeleted(videoComment) | ||
134 | |||
135 | await videoComment.save() | ||
136 | }) | ||
132 | 137 | ||
133 | if (videoComment.Video.isOwned()) { | 138 | if (videoComment.Video.isOwned()) { |
134 | // Don't resend the activity to the sender | 139 | // Don't resend the activity to the sender |
diff --git a/server/lib/video-comment.ts b/server/lib/video-comment.ts index bb811bd2c..b8074e6d2 100644 --- a/server/lib/video-comment.ts +++ b/server/lib/video-comment.ts | |||
@@ -73,9 +73,16 @@ function buildFormattedCommentTree (resultList: ResultList<VideoCommentModel>): | |||
73 | return thread | 73 | return thread |
74 | } | 74 | } |
75 | 75 | ||
76 | function markCommentAsDeleted (comment: MCommentOwnerVideoReply): void { | ||
77 | comment.text = '' | ||
78 | comment.deletedAt = new Date() | ||
79 | comment.accountId = null | ||
80 | } | ||
81 | |||
76 | // --------------------------------------------------------------------------- | 82 | // --------------------------------------------------------------------------- |
77 | 83 | ||
78 | export { | 84 | export { |
79 | createVideoComment, | 85 | createVideoComment, |
80 | buildFormattedCommentTree | 86 | buildFormattedCommentTree, |
87 | markCommentAsDeleted | ||
81 | } | 88 | } |
diff --git a/server/models/account/account.ts b/server/models/account/account.ts index ba1094536..a818a5a4d 100644 --- a/server/models/account/account.ts +++ b/server/models/account/account.ts | |||
@@ -201,7 +201,7 @@ export class AccountModel extends Model<AccountModel> { | |||
201 | 201 | ||
202 | @HasMany(() => VideoCommentModel, { | 202 | @HasMany(() => VideoCommentModel, { |
203 | foreignKey: { | 203 | foreignKey: { |
204 | allowNull: false | 204 | allowNull: true |
205 | }, | 205 | }, |
206 | onDelete: 'cascade', | 206 | onDelete: 'cascade', |
207 | hooks: true | 207 | hooks: true |
diff --git a/server/models/video/video-comment.ts b/server/models/video/video-comment.ts index 2e4220434..b44d65138 100644 --- a/server/models/video/video-comment.ts +++ b/server/models/video/video-comment.ts | |||
@@ -1,5 +1,5 @@ | |||
1 | import { AllowNull, BelongsTo, Column, CreatedAt, DataType, ForeignKey, Is, Model, Scopes, Table, UpdatedAt } from 'sequelize-typescript' | 1 | import { AllowNull, BelongsTo, Column, CreatedAt, DataType, ForeignKey, Is, Model, Scopes, Table, UpdatedAt } from 'sequelize-typescript' |
2 | import { ActivityTagObject } from '../../../shared/models/activitypub/objects/common-objects' | 2 | import { ActivityTagObject, ActivityTombstoneObject } from '../../../shared/models/activitypub/objects/common-objects' |
3 | import { VideoCommentObject } from '../../../shared/models/activitypub/objects/video-comment-object' | 3 | import { VideoCommentObject } from '../../../shared/models/activitypub/objects/video-comment-object' |
4 | import { VideoComment } from '../../../shared/models/videos/video-comment.model' | 4 | import { VideoComment } from '../../../shared/models/videos/video-comment.model' |
5 | import { isActivityPubUrlValid } from '../../helpers/custom-validators/activitypub/misc' | 5 | import { isActivityPubUrlValid } from '../../helpers/custom-validators/activitypub/misc' |
@@ -122,6 +122,10 @@ export class VideoCommentModel extends Model<VideoCommentModel> { | |||
122 | @UpdatedAt | 122 | @UpdatedAt |
123 | updatedAt: Date | 123 | updatedAt: Date |
124 | 124 | ||
125 | @AllowNull(true) | ||
126 | @Column(DataType.DATE) | ||
127 | deletedAt: Date | ||
128 | |||
125 | @AllowNull(false) | 129 | @AllowNull(false) |
126 | @Is('VideoCommentUrl', value => throwIfNotValid(value, isActivityPubUrlValid, 'url')) | 130 | @Is('VideoCommentUrl', value => throwIfNotValid(value, isActivityPubUrlValid, 'url')) |
127 | @Column(DataType.STRING(CONSTRAINTS_FIELDS.VIDEOS.URL.max)) | 131 | @Column(DataType.STRING(CONSTRAINTS_FIELDS.VIDEOS.URL.max)) |
@@ -177,7 +181,7 @@ export class VideoCommentModel extends Model<VideoCommentModel> { | |||
177 | 181 | ||
178 | @BelongsTo(() => AccountModel, { | 182 | @BelongsTo(() => AccountModel, { |
179 | foreignKey: { | 183 | foreignKey: { |
180 | allowNull: false | 184 | allowNull: true |
181 | }, | 185 | }, |
182 | onDelete: 'CASCADE' | 186 | onDelete: 'CASCADE' |
183 | }) | 187 | }) |
@@ -436,9 +440,17 @@ export class VideoCommentModel extends Model<VideoCommentModel> { | |||
436 | } | 440 | } |
437 | 441 | ||
438 | isOwned () { | 442 | isOwned () { |
443 | if (!this.Account) { | ||
444 | return false | ||
445 | } | ||
446 | |||
439 | return this.Account.isOwned() | 447 | return this.Account.isOwned() |
440 | } | 448 | } |
441 | 449 | ||
450 | isDeleted () { | ||
451 | return null !== this.deletedAt | ||
452 | } | ||
453 | |||
442 | extractMentions () { | 454 | extractMentions () { |
443 | let result: string[] = [] | 455 | let result: string[] = [] |
444 | 456 | ||
@@ -487,12 +499,25 @@ export class VideoCommentModel extends Model<VideoCommentModel> { | |||
487 | videoId: this.videoId, | 499 | videoId: this.videoId, |
488 | createdAt: this.createdAt, | 500 | createdAt: this.createdAt, |
489 | updatedAt: this.updatedAt, | 501 | updatedAt: this.updatedAt, |
502 | deletedAt: this.deletedAt, | ||
503 | isDeleted: this.isDeleted(), | ||
490 | totalReplies: this.get('totalReplies') || 0, | 504 | totalReplies: this.get('totalReplies') || 0, |
491 | account: this.Account.toFormattedJSON() | 505 | account: this.Account ? this.Account.toFormattedJSON() : null |
492 | } as VideoComment | 506 | } as VideoComment |
493 | } | 507 | } |
494 | 508 | ||
495 | toActivityPubObject (this: MCommentAP, threadParentComments: MCommentOwner[]): VideoCommentObject { | 509 | toActivityPubObject (this: MCommentAP, threadParentComments: MCommentOwner[]): VideoCommentObject | ActivityTombstoneObject { |
510 | if (this.isDeleted()) { | ||
511 | return { | ||
512 | id: this.url, | ||
513 | type: 'Tombstone', | ||
514 | formerType: 'Note', | ||
515 | published: this.createdAt.toISOString(), | ||
516 | updated: this.updatedAt.toISOString(), | ||
517 | deleted: this.deletedAt.toISOString() | ||
518 | } | ||
519 | } | ||
520 | |||
496 | let inReplyTo: string | 521 | let inReplyTo: string |
497 | // New thread, so in AS we reply to the video | 522 | // New thread, so in AS we reply to the video |
498 | if (this.inReplyToCommentId === null) { | 523 | if (this.inReplyToCommentId === null) { |
diff --git a/server/tests/api/videos/multiple-servers.ts b/server/tests/api/videos/multiple-servers.ts index aeda188c2..e7b57ba1f 100644 --- a/server/tests/api/videos/multiple-servers.ts +++ b/server/tests/api/videos/multiple-servers.ts | |||
@@ -868,7 +868,7 @@ describe('Test multiple servers', function () { | |||
868 | await waitJobs(servers) | 868 | await waitJobs(servers) |
869 | }) | 869 | }) |
870 | 870 | ||
871 | it('Should not have this comment anymore', async function () { | 871 | it('Should have this comment marked as deleted', async function () { |
872 | for (const server of servers) { | 872 | for (const server of servers) { |
873 | const res1 = await getVideoCommentThreads(server.url, videoUUID, 0, 5) | 873 | const res1 = await getVideoCommentThreads(server.url, videoUUID, 0, 5) |
874 | const threadId = res1.body.data.find(c => c.text === 'my super first comment').id | 874 | const threadId = res1.body.data.find(c => c.text === 'my super first comment').id |
@@ -880,7 +880,13 @@ describe('Test multiple servers', function () { | |||
880 | 880 | ||
881 | const firstChild = tree.children[0] | 881 | const firstChild = tree.children[0] |
882 | expect(firstChild.comment.text).to.equal('my super answer to thread 1') | 882 | expect(firstChild.comment.text).to.equal('my super answer to thread 1') |
883 | expect(firstChild.children).to.have.lengthOf(0) | 883 | expect(firstChild.children).to.have.lengthOf(1) |
884 | |||
885 | const deletedComment = firstChild.children[0].comment | ||
886 | expect(deletedComment.isDeleted).to.be.true | ||
887 | expect(deletedComment.deletedAt).to.not.be.null | ||
888 | expect(deletedComment.account).to.be.null | ||
889 | expect(deletedComment.text).to.equal('') | ||
884 | 890 | ||
885 | const secondChild = tree.children[1] | 891 | const secondChild = tree.children[1] |
886 | expect(secondChild.comment.text).to.equal('my second answer to thread 1') | 892 | expect(secondChild.comment.text).to.equal('my second answer to thread 1') |
@@ -897,13 +903,13 @@ describe('Test multiple servers', function () { | |||
897 | await waitJobs(servers) | 903 | await waitJobs(servers) |
898 | }) | 904 | }) |
899 | 905 | ||
900 | it('Should have the threads deleted on other servers too', async function () { | 906 | it('Should have the threads marked as deleted on other servers too', async function () { |
901 | for (const server of servers) { | 907 | for (const server of servers) { |
902 | const res = await getVideoCommentThreads(server.url, videoUUID, 0, 5) | 908 | const res = await getVideoCommentThreads(server.url, videoUUID, 0, 5) |
903 | 909 | ||
904 | expect(res.body.total).to.equal(1) | 910 | expect(res.body.total).to.equal(2) |
905 | expect(res.body.data).to.be.an('array') | 911 | expect(res.body.data).to.be.an('array') |
906 | expect(res.body.data).to.have.lengthOf(1) | 912 | expect(res.body.data).to.have.lengthOf(2) |
907 | 913 | ||
908 | { | 914 | { |
909 | const comment: VideoComment = res.body.data[0] | 915 | const comment: VideoComment = res.body.data[0] |
@@ -915,6 +921,20 @@ describe('Test multiple servers', function () { | |||
915 | expect(dateIsValid(comment.createdAt as string)).to.be.true | 921 | expect(dateIsValid(comment.createdAt as string)).to.be.true |
916 | expect(dateIsValid(comment.updatedAt as string)).to.be.true | 922 | expect(dateIsValid(comment.updatedAt as string)).to.be.true |
917 | } | 923 | } |
924 | |||
925 | { | ||
926 | const deletedComment: VideoComment = res.body.data[1] | ||
927 | expect(deletedComment).to.not.be.undefined | ||
928 | expect(deletedComment.isDeleted).to.be.true | ||
929 | expect(deletedComment.deletedAt).to.not.be.null | ||
930 | expect(deletedComment.text).to.equal('') | ||
931 | expect(deletedComment.inReplyToCommentId).to.be.null | ||
932 | expect(deletedComment.account).to.be.null | ||
933 | expect(deletedComment.totalReplies).to.equal(3) | ||
934 | expect(dateIsValid(deletedComment.createdAt as string)).to.be.true | ||
935 | expect(dateIsValid(deletedComment.updatedAt as string)).to.be.true | ||
936 | expect(dateIsValid(deletedComment.deletedAt as string)).to.be.true | ||
937 | } | ||
918 | } | 938 | } |
919 | }) | 939 | }) |
920 | 940 | ||
@@ -926,12 +946,32 @@ describe('Test multiple servers', function () { | |||
926 | await waitJobs(servers) | 946 | await waitJobs(servers) |
927 | }) | 947 | }) |
928 | 948 | ||
929 | it('Should have the threads deleted on other servers too', async function () { | 949 | it('Should have the threads marked as deleted on other servers too', async function () { |
930 | for (const server of servers) { | 950 | for (const server of servers) { |
931 | const res = await getVideoCommentThreads(server.url, videoUUID, 0, 5) | 951 | const res = await getVideoCommentThreads(server.url, videoUUID, 0, 5) |
932 | 952 | ||
933 | expect(res.body.total).to.equal(0) | 953 | expect(res.body.total).to.equal(2) |
934 | expect(res.body.data).to.have.lengthOf(0) | 954 | expect(res.body.data).to.have.lengthOf(2) |
955 | |||
956 | { | ||
957 | const comment: VideoComment = res.body.data[0] | ||
958 | expect(comment.text).to.equal('') | ||
959 | expect(comment.isDeleted).to.be.true | ||
960 | expect(comment.createdAt).to.not.be.null | ||
961 | expect(comment.deletedAt).to.not.be.null | ||
962 | expect(comment.account).to.be.null | ||
963 | expect(comment.totalReplies).to.equal(0) | ||
964 | } | ||
965 | |||
966 | { | ||
967 | const comment: VideoComment = res.body.data[1] | ||
968 | expect(comment.text).to.equal('') | ||
969 | expect(comment.isDeleted).to.be.true | ||
970 | expect(comment.createdAt).to.not.be.null | ||
971 | expect(comment.deletedAt).to.not.be.null | ||
972 | expect(comment.account).to.be.null | ||
973 | expect(comment.totalReplies).to.equal(3) | ||
974 | } | ||
935 | } | 975 | } |
936 | }) | 976 | }) |
937 | 977 | ||
diff --git a/server/tests/api/videos/video-comments.ts b/server/tests/api/videos/video-comments.ts index 82182cc7c..95be14c0e 100644 --- a/server/tests/api/videos/video-comments.ts +++ b/server/tests/api/videos/video-comments.ts | |||
@@ -172,7 +172,7 @@ describe('Test video comments', function () { | |||
172 | 172 | ||
173 | const tree: VideoCommentThreadTree = res.body | 173 | const tree: VideoCommentThreadTree = res.body |
174 | expect(tree.comment.text).equal('my super first comment') | 174 | expect(tree.comment.text).equal('my super first comment') |
175 | expect(tree.children).to.have.lengthOf(1) | 175 | expect(tree.children).to.have.lengthOf(2) |
176 | 176 | ||
177 | const firstChild = tree.children[0] | 177 | const firstChild = tree.children[0] |
178 | expect(firstChild.comment.text).to.equal('my super answer to thread 1') | 178 | expect(firstChild.comment.text).to.equal('my super answer to thread 1') |
@@ -181,20 +181,32 @@ describe('Test video comments', function () { | |||
181 | const childOfFirstChild = firstChild.children[0] | 181 | const childOfFirstChild = firstChild.children[0] |
182 | expect(childOfFirstChild.comment.text).to.equal('my super answer to answer of thread 1') | 182 | expect(childOfFirstChild.comment.text).to.equal('my super answer to answer of thread 1') |
183 | expect(childOfFirstChild.children).to.have.lengthOf(0) | 183 | expect(childOfFirstChild.children).to.have.lengthOf(0) |
184 | |||
185 | const deletedChildOfFirstChild = tree.children[1] | ||
186 | expect(deletedChildOfFirstChild.comment.text).to.equal('') | ||
187 | expect(deletedChildOfFirstChild.comment.isDeleted).to.be.true | ||
188 | expect(deletedChildOfFirstChild.comment.deletedAt).to.not.be.null | ||
189 | expect(deletedChildOfFirstChild.comment.account).to.be.null | ||
190 | expect(deletedChildOfFirstChild.children).to.have.lengthOf(0) | ||
184 | }) | 191 | }) |
185 | 192 | ||
186 | it('Should delete a complete thread', async function () { | 193 | it('Should delete a complete thread', async function () { |
187 | await deleteVideoComment(server.url, server.accessToken, videoId, threadId) | 194 | await deleteVideoComment(server.url, server.accessToken, videoId, threadId) |
188 | 195 | ||
189 | const res = await getVideoCommentThreads(server.url, videoUUID, 0, 5, 'createdAt') | 196 | const res = await getVideoCommentThreads(server.url, videoUUID, 0, 5, 'createdAt') |
190 | expect(res.body.total).to.equal(2) | 197 | expect(res.body.total).to.equal(3) |
191 | expect(res.body.data).to.be.an('array') | 198 | expect(res.body.data).to.be.an('array') |
192 | expect(res.body.data).to.have.lengthOf(2) | 199 | expect(res.body.data).to.have.lengthOf(3) |
193 | 200 | ||
194 | expect(res.body.data[0].text).to.equal('super thread 2') | 201 | expect(res.body.data[0].text).to.equal('') |
195 | expect(res.body.data[0].totalReplies).to.equal(0) | 202 | expect(res.body.data[0].isDeleted).to.be.true |
196 | expect(res.body.data[1].text).to.equal('super thread 3') | 203 | expect(res.body.data[0].deletedAt).to.not.be.null |
204 | expect(res.body.data[0].account).to.be.null | ||
205 | expect(res.body.data[0].totalReplies).to.equal(3) | ||
206 | expect(res.body.data[1].text).to.equal('super thread 2') | ||
197 | expect(res.body.data[1].totalReplies).to.equal(0) | 207 | expect(res.body.data[1].totalReplies).to.equal(0) |
208 | expect(res.body.data[2].text).to.equal('super thread 3') | ||
209 | expect(res.body.data[2].totalReplies).to.equal(0) | ||
198 | }) | 210 | }) |
199 | 211 | ||
200 | after(async function () { | 212 | after(async function () { |