mirror of https://github.com/Chocobozzz/PeerTube
Fix video comments display with deleted comments
parent
fae6e4da8f
commit
9d6b9d10ef
|
@ -1,4 +1,4 @@
|
||||||
<div *ngIf="isNotDeletedOrDeletedWithReplies()" class="root-comment">
|
<div *ngIf="isCommentDisplayed()" class="root-comment">
|
||||||
<div class="left">
|
<div class="left">
|
||||||
<a *ngIf="!comment.isDeleted" [href]="comment.account.url" target="_blank" rel="noopener noreferrer">
|
<a *ngIf="!comment.isDeleted" [href]="comment.account.url" target="_blank" rel="noopener noreferrer">
|
||||||
<img
|
<img
|
||||||
|
|
|
@ -62,6 +62,7 @@ export class VideoCommentComponent implements OnInit, OnChanges {
|
||||||
if (!this.commentTree) {
|
if (!this.commentTree) {
|
||||||
this.commentTree = {
|
this.commentTree = {
|
||||||
comment: this.comment,
|
comment: this.comment,
|
||||||
|
hasDisplayedChildren: false,
|
||||||
children: []
|
children: []
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -70,6 +71,7 @@ export class VideoCommentComponent implements OnInit, OnChanges {
|
||||||
|
|
||||||
this.commentTree.children.unshift({
|
this.commentTree.children.unshift({
|
||||||
comment: createdComment,
|
comment: createdComment,
|
||||||
|
hasDisplayedChildren: false,
|
||||||
children: []
|
children: []
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -133,8 +135,11 @@ export class VideoCommentComponent implements OnInit, OnChanges {
|
||||||
($event.target as HTMLImageElement).src = Account.GET_DEFAULT_AVATAR_URL()
|
($event.target as HTMLImageElement).src = Account.GET_DEFAULT_AVATAR_URL()
|
||||||
}
|
}
|
||||||
|
|
||||||
isNotDeletedOrDeletedWithReplies () {
|
isCommentDisplayed () {
|
||||||
return !this.comment.isDeleted || this.comment.isDeleted && this.comment.totalReplies !== 0
|
// Not deleted
|
||||||
|
return !this.comment.isDeleted ||
|
||||||
|
this.comment.totalReplies !== 0 || // Or root comment thread has replies
|
||||||
|
(this.commentTree?.hasDisplayedChildren) // Or this is a reply that have other replies
|
||||||
}
|
}
|
||||||
|
|
||||||
private getUserIfNeeded (account: Account) {
|
private getUserIfNeeded (account: Account) {
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
<div>
|
<div>
|
||||||
<div class="title-block">
|
<div class="title-block">
|
||||||
<h2 class="title-page title-page-single">
|
<h2 class="title-page title-page-single">
|
||||||
<ng-container *ngIf="componentPagination.totalItems > 0; then hasComments; else noComments"></ng-container>
|
<ng-container *ngIf="totalNotDeletedComments > 0; then hasComments; else noComments"></ng-container>
|
||||||
<ng-template #hasComments>
|
<ng-template #hasComments>
|
||||||
<ng-container i18n *ngIf="componentPagination.totalItems === 1; else manyComments">1 Comment</ng-container>
|
<ng-container i18n *ngIf="totalNotDeletedComments === 1; else manyComments">1 Comment</ng-container>
|
||||||
<ng-template i18n #manyComments>{{ componentPagination.totalItems }} Comments</ng-template>
|
<ng-template i18n #manyComments>{{ totalNotDeletedComments }} Comments</ng-template>
|
||||||
</ng-template>
|
</ng-template>
|
||||||
<ng-template i18n #noComments>Comments</ng-template>
|
<ng-template i18n #noComments>Comments</ng-template>
|
||||||
</h2>
|
</h2>
|
||||||
|
@ -30,7 +30,7 @@
|
||||||
[textValue]="commentThreadRedraftValue"
|
[textValue]="commentThreadRedraftValue"
|
||||||
></my-video-comment-add>
|
></my-video-comment-add>
|
||||||
|
|
||||||
<div *ngIf="componentPagination.totalItems === 0 && comments.length === 0" i18n>No comments.</div>
|
<div *ngIf="totalNotDeletedComments === 0 && comments.length === 0" i18n>No comments.</div>
|
||||||
|
|
||||||
<div
|
<div
|
||||||
class="comment-threads"
|
class="comment-threads"
|
||||||
|
|
|
@ -21,15 +21,20 @@ export class VideoCommentsComponent implements OnInit, OnChanges, OnDestroy {
|
||||||
|
|
||||||
comments: VideoComment[] = []
|
comments: VideoComment[] = []
|
||||||
highlightedThread: VideoComment
|
highlightedThread: VideoComment
|
||||||
|
|
||||||
sort = '-createdAt'
|
sort = '-createdAt'
|
||||||
|
|
||||||
componentPagination: ComponentPagination = {
|
componentPagination: ComponentPagination = {
|
||||||
currentPage: 1,
|
currentPage: 1,
|
||||||
itemsPerPage: 10,
|
itemsPerPage: 10,
|
||||||
totalItems: null
|
totalItems: null
|
||||||
}
|
}
|
||||||
|
totalNotDeletedComments: number
|
||||||
|
|
||||||
inReplyToCommentId: number
|
inReplyToCommentId: number
|
||||||
commentReplyRedraftValue: string
|
commentReplyRedraftValue: string
|
||||||
commentThreadRedraftValue: string
|
commentThreadRedraftValue: string
|
||||||
|
|
||||||
threadComments: { [ id: number ]: VideoCommentThreadTree } = {}
|
threadComments: { [ id: number ]: VideoCommentThreadTree } = {}
|
||||||
threadLoading: { [ id: number ]: boolean } = {}
|
threadLoading: { [ id: number ]: boolean } = {}
|
||||||
|
|
||||||
|
@ -122,8 +127,8 @@ export class VideoCommentsComponent implements OnInit, OnChanges, OnDestroy {
|
||||||
obs.subscribe(
|
obs.subscribe(
|
||||||
res => {
|
res => {
|
||||||
this.comments = this.comments.concat(res.data)
|
this.comments = this.comments.concat(res.data)
|
||||||
// Client does not display removed comments
|
this.componentPagination.totalItems = res.total
|
||||||
this.componentPagination.totalItems = res.total - this.comments.filter(c => c.isDeleted).length
|
this.totalNotDeletedComments = res.totalNotDeletedComments
|
||||||
|
|
||||||
this.onDataSubject.next(res.data)
|
this.onDataSubject.next(res.data)
|
||||||
this.hooks.runAction('action:video-watch.video-threads.loaded', 'video-watch', { data: this.componentPagination })
|
this.hooks.runAction('action:video-watch.video-threads.loaded', 'video-watch', { data: this.componentPagination })
|
||||||
|
@ -241,6 +246,7 @@ export class VideoCommentsComponent implements OnInit, OnChanges, OnDestroy {
|
||||||
this.inReplyToCommentId = undefined
|
this.inReplyToCommentId = undefined
|
||||||
this.componentPagination.currentPage = 1
|
this.componentPagination.currentPage = 1
|
||||||
this.componentPagination.totalItems = null
|
this.componentPagination.totalItems = null
|
||||||
|
this.totalNotDeletedComments = null
|
||||||
|
|
||||||
this.syndicationItems = this.videoCommentService.getVideoCommentsFeeds(this.video.uuid)
|
this.syndicationItems = this.videoCommentService.getVideoCommentsFeeds(this.video.uuid)
|
||||||
this.loadMoreThreads()
|
this.loadMoreThreads()
|
||||||
|
|
|
@ -3,5 +3,6 @@ import { VideoComment } from './video-comment.model'
|
||||||
|
|
||||||
export class VideoCommentThreadTree implements VideoCommentThreadTreeServerModel {
|
export class VideoCommentThreadTree implements VideoCommentThreadTreeServerModel {
|
||||||
comment: VideoComment
|
comment: VideoComment
|
||||||
|
hasDisplayedChildren: boolean
|
||||||
children: VideoCommentThreadTree[]
|
children: VideoCommentThreadTree[]
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,6 +8,7 @@ import { objectLineFeedToHtml } from '@app/helpers'
|
||||||
import {
|
import {
|
||||||
FeedFormat,
|
FeedFormat,
|
||||||
ResultList,
|
ResultList,
|
||||||
|
ThreadsResultList,
|
||||||
VideoComment as VideoCommentServerModel,
|
VideoComment as VideoCommentServerModel,
|
||||||
VideoCommentAdmin,
|
VideoCommentAdmin,
|
||||||
VideoCommentCreate,
|
VideoCommentCreate,
|
||||||
|
@ -76,7 +77,7 @@ export class VideoCommentService {
|
||||||
videoId: number | string,
|
videoId: number | string,
|
||||||
componentPagination: ComponentPaginationLight,
|
componentPagination: ComponentPaginationLight,
|
||||||
sort: string
|
sort: string
|
||||||
}): Observable<ResultList<VideoComment>> {
|
}): Observable<ThreadsResultList<VideoComment>> {
|
||||||
const { videoId, componentPagination, sort } = parameters
|
const { videoId, componentPagination, sort } = parameters
|
||||||
|
|
||||||
const pagination = this.restService.componentPaginationToRestPagination(componentPagination)
|
const pagination = this.restService.componentPaginationToRestPagination(componentPagination)
|
||||||
|
@ -85,7 +86,7 @@ export class VideoCommentService {
|
||||||
params = this.restService.addRestGetParams(params, pagination, sort)
|
params = this.restService.addRestGetParams(params, pagination, sort)
|
||||||
|
|
||||||
const url = VideoCommentService.BASE_VIDEO_URL + videoId + '/comment-threads'
|
const url = VideoCommentService.BASE_VIDEO_URL + videoId + '/comment-threads'
|
||||||
return this.authHttp.get<ResultList<VideoComment>>(url, { params })
|
return this.authHttp.get<ThreadsResultList<VideoComment>>(url, { params })
|
||||||
.pipe(
|
.pipe(
|
||||||
map(result => this.extractVideoComments(result)),
|
map(result => this.extractVideoComments(result)),
|
||||||
catchError(err => this.restExtractor.handleError(err))
|
catchError(err => this.restExtractor.handleError(err))
|
||||||
|
@ -158,7 +159,7 @@ export class VideoCommentService {
|
||||||
return new VideoComment(videoComment)
|
return new VideoComment(videoComment)
|
||||||
}
|
}
|
||||||
|
|
||||||
private extractVideoComments (result: ResultList<VideoCommentServerModel>) {
|
private extractVideoComments (result: ThreadsResultList<VideoCommentServerModel>) {
|
||||||
const videoCommentsJson = result.data
|
const videoCommentsJson = result.data
|
||||||
const totalComments = result.total
|
const totalComments = result.total
|
||||||
const comments: VideoComment[] = []
|
const comments: VideoComment[] = []
|
||||||
|
@ -167,16 +168,22 @@ export class VideoCommentService {
|
||||||
comments.push(new VideoComment(videoCommentJson))
|
comments.push(new VideoComment(videoCommentJson))
|
||||||
}
|
}
|
||||||
|
|
||||||
return { data: comments, total: totalComments }
|
return { data: comments, total: totalComments, totalNotDeletedComments: result.totalNotDeletedComments }
|
||||||
}
|
}
|
||||||
|
|
||||||
private extractVideoCommentTree (tree: VideoCommentThreadTreeServerModel) {
|
private extractVideoCommentTree (serverTree: VideoCommentThreadTreeServerModel): VideoCommentThreadTree {
|
||||||
if (!tree) return tree as VideoCommentThreadTree
|
if (!serverTree) return null
|
||||||
|
|
||||||
tree.comment = new VideoComment(tree.comment)
|
const tree = {
|
||||||
tree.children.forEach(c => this.extractVideoCommentTree(c))
|
comment: new VideoComment(serverTree.comment),
|
||||||
|
children: serverTree.children.map(c => this.extractVideoCommentTree(c))
|
||||||
|
}
|
||||||
|
|
||||||
return tree as VideoCommentThreadTree
|
const hasDisplayedChildren = tree.children.length === 0
|
||||||
|
? !tree.comment.isDeleted
|
||||||
|
: tree.children.some(c => c.hasDisplayedChildren)
|
||||||
|
|
||||||
|
return Object.assign(tree, { hasDisplayedChildren })
|
||||||
}
|
}
|
||||||
|
|
||||||
private buildParamsFromSearch (search: string, params: HttpParams) {
|
private buildParamsFromSearch (search: string, params: HttpParams) {
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import * as express from 'express'
|
import * as express from 'express'
|
||||||
import { ResultList, UserRight } from '../../../../shared/models'
|
import { ResultList, ThreadsResultList, UserRight } from '../../../../shared/models'
|
||||||
import { VideoCommentCreate } from '../../../../shared/models/videos/video-comment.model'
|
import { VideoCommentCreate } from '../../../../shared/models/videos/video-comment.model'
|
||||||
import { auditLoggerFactory, CommentAuditView, getAuditIdFromRes } from '../../../helpers/audit-logger'
|
import { auditLoggerFactory, CommentAuditView, getAuditIdFromRes } from '../../../helpers/audit-logger'
|
||||||
import { getFormattedObjects } from '../../../helpers/utils'
|
import { getFormattedObjects } from '../../../helpers/utils'
|
||||||
|
@ -30,6 +30,7 @@ import {
|
||||||
import { AccountModel } from '../../../models/account/account'
|
import { AccountModel } from '../../../models/account/account'
|
||||||
import { VideoCommentModel } from '../../../models/video/video-comment'
|
import { VideoCommentModel } from '../../../models/video/video-comment'
|
||||||
import { HttpStatusCode } from '../../../../shared/core-utils/miscs/http-error-codes'
|
import { HttpStatusCode } from '../../../../shared/core-utils/miscs/http-error-codes'
|
||||||
|
import { logger } from '@server/helpers/logger'
|
||||||
|
|
||||||
const auditLogger = auditLoggerFactory('comments')
|
const auditLogger = auditLoggerFactory('comments')
|
||||||
const videoCommentRouter = express.Router()
|
const videoCommentRouter = express.Router()
|
||||||
|
@ -108,7 +109,7 @@ async function listVideoThreads (req: express.Request, res: express.Response) {
|
||||||
const video = res.locals.onlyVideo
|
const video = res.locals.onlyVideo
|
||||||
const user = res.locals.oauth ? res.locals.oauth.token.User : undefined
|
const user = res.locals.oauth ? res.locals.oauth.token.User : undefined
|
||||||
|
|
||||||
let resultList: ResultList<VideoCommentModel>
|
let resultList: ThreadsResultList<VideoCommentModel>
|
||||||
|
|
||||||
if (video.commentsEnabled === true) {
|
if (video.commentsEnabled === true) {
|
||||||
const apiOptions = await Hooks.wrapObject({
|
const apiOptions = await Hooks.wrapObject({
|
||||||
|
@ -128,11 +129,15 @@ async function listVideoThreads (req: express.Request, res: express.Response) {
|
||||||
} else {
|
} else {
|
||||||
resultList = {
|
resultList = {
|
||||||
total: 0,
|
total: 0,
|
||||||
|
totalNotDeletedComments: 0,
|
||||||
data: []
|
data: []
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return res.json(getFormattedObjects(resultList.data, resultList.total))
|
return res.json({
|
||||||
|
...getFormattedObjects(resultList.data, resultList.total),
|
||||||
|
totalNotDeletedComments: resultList.totalNotDeletedComments
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
async function listVideoThreadComments (req: express.Request, res: express.Response) {
|
async function listVideoThreadComments (req: express.Request, res: express.Response) {
|
||||||
|
@ -161,6 +166,8 @@ async function listVideoThreadComments (req: express.Request, res: express.Respo
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
logger.info('coucou', { resultList })
|
||||||
|
|
||||||
if (resultList.data.length === 0) {
|
if (resultList.data.length === 0) {
|
||||||
return res.sendStatus(HttpStatusCode.NOT_FOUND_404)
|
return res.sendStatus(HttpStatusCode.NOT_FOUND_404)
|
||||||
}
|
}
|
||||||
|
|
|
@ -134,7 +134,7 @@ function buildBlockedAccountSQL (blockerIds: number[]) {
|
||||||
const blockerIdsString = blockerIds.join(', ')
|
const blockerIdsString = blockerIds.join(', ')
|
||||||
|
|
||||||
return 'SELECT "targetAccountId" AS "id" FROM "accountBlocklist" WHERE "accountId" IN (' + blockerIdsString + ')' +
|
return 'SELECT "targetAccountId" AS "id" FROM "accountBlocklist" WHERE "accountId" IN (' + blockerIdsString + ')' +
|
||||||
' UNION ALL ' +
|
' UNION ' +
|
||||||
'SELECT "account"."id" AS "id" FROM account INNER JOIN "actor" ON account."actorId" = actor.id ' +
|
'SELECT "account"."id" AS "id" FROM account INNER JOIN "actor" ON account."actorId" = actor.id ' +
|
||||||
'INNER JOIN "serverBlocklist" ON "actor"."serverId" = "serverBlocklist"."targetServerId" ' +
|
'INNER JOIN "serverBlocklist" ON "actor"."serverId" = "serverBlocklist"."targetServerId" ' +
|
||||||
'WHERE "serverBlocklist"."accountId" IN (' + blockerIdsString + ')'
|
'WHERE "serverBlocklist"."accountId" IN (' + blockerIdsString + ')'
|
||||||
|
|
|
@ -414,7 +414,15 @@ export class VideoCommentModel extends Model {
|
||||||
|
|
||||||
const blockerAccountIds = await VideoCommentModel.buildBlockerAccountIds({ videoId, user, isVideoOwned })
|
const blockerAccountIds = await VideoCommentModel.buildBlockerAccountIds({ videoId, user, isVideoOwned })
|
||||||
|
|
||||||
const query = {
|
const accountBlockedWhere = {
|
||||||
|
accountId: {
|
||||||
|
[Op.notIn]: Sequelize.literal(
|
||||||
|
'(' + buildBlockedAccountSQL(blockerAccountIds) + ')'
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const queryList = {
|
||||||
offset: start,
|
offset: start,
|
||||||
limit: count,
|
limit: count,
|
||||||
order: getCommentSort(sort),
|
order: getCommentSort(sort),
|
||||||
|
@ -428,13 +436,7 @@ export class VideoCommentModel extends Model {
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
[Op.or]: [
|
[Op.or]: [
|
||||||
{
|
accountBlockedWhere,
|
||||||
accountId: {
|
|
||||||
[Op.notIn]: Sequelize.literal(
|
|
||||||
'(' + buildBlockedAccountSQL(blockerAccountIds) + ')'
|
|
||||||
)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
accountId: null
|
accountId: null
|
||||||
}
|
}
|
||||||
|
@ -444,19 +446,27 @@ export class VideoCommentModel extends Model {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const scopes: (string | ScopeOptions)[] = [
|
const scopesList: (string | ScopeOptions)[] = [
|
||||||
ScopeNames.WITH_ACCOUNT_FOR_API,
|
ScopeNames.WITH_ACCOUNT_FOR_API,
|
||||||
{
|
{
|
||||||
method: [ ScopeNames.ATTRIBUTES_FOR_API, blockerAccountIds ]
|
method: [ ScopeNames.ATTRIBUTES_FOR_API, blockerAccountIds ]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
||||||
return VideoCommentModel
|
const queryCount = {
|
||||||
.scope(scopes)
|
where: {
|
||||||
.findAndCountAll(query)
|
videoId,
|
||||||
.then(({ rows, count }) => {
|
deletedAt: null,
|
||||||
return { total: count, data: rows }
|
...accountBlockedWhere
|
||||||
})
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return Promise.all([
|
||||||
|
VideoCommentModel.scope(scopesList).findAndCountAll(queryList),
|
||||||
|
VideoCommentModel.count(queryCount)
|
||||||
|
]).then(([ { rows, count }, totalNotDeletedComments ]) => {
|
||||||
|
return { total: count, data: rows, totalNotDeletedComments }
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
static async listThreadCommentsForApi (parameters: {
|
static async listThreadCommentsForApi (parameters: {
|
||||||
|
@ -477,11 +487,18 @@ export class VideoCommentModel extends Model {
|
||||||
{ id: threadId },
|
{ id: threadId },
|
||||||
{ originCommentId: threadId }
|
{ originCommentId: threadId }
|
||||||
],
|
],
|
||||||
accountId: {
|
[Op.or]: [
|
||||||
[Op.notIn]: Sequelize.literal(
|
{
|
||||||
'(' + buildBlockedAccountSQL(blockerAccountIds) + ')'
|
accountId: {
|
||||||
)
|
[Op.notIn]: Sequelize.literal(
|
||||||
}
|
'(' + buildBlockedAccountSQL(blockerAccountIds) + ')'
|
||||||
|
)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
accountId: null
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -492,8 +509,7 @@ export class VideoCommentModel extends Model {
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
||||||
return VideoCommentModel
|
return VideoCommentModel.scope(scopes)
|
||||||
.scope(scopes)
|
|
||||||
.findAndCountAll(query)
|
.findAndCountAll(query)
|
||||||
.then(({ rows, count }) => {
|
.then(({ rows, count }) => {
|
||||||
return { total: count, data: rows }
|
return { total: count, data: rows }
|
||||||
|
|
|
@ -67,6 +67,7 @@ describe('Test video comments', function () {
|
||||||
const res = await getVideoCommentThreads(server.url, videoUUID, 0, 5)
|
const res = await getVideoCommentThreads(server.url, videoUUID, 0, 5)
|
||||||
|
|
||||||
expect(res.body.total).to.equal(0)
|
expect(res.body.total).to.equal(0)
|
||||||
|
expect(res.body.totalNotDeletedComments).to.equal(0)
|
||||||
expect(res.body.data).to.be.an('array')
|
expect(res.body.data).to.be.an('array')
|
||||||
expect(res.body.data).to.have.lengthOf(0)
|
expect(res.body.data).to.have.lengthOf(0)
|
||||||
})
|
})
|
||||||
|
@ -94,6 +95,7 @@ describe('Test video comments', function () {
|
||||||
const res = await getVideoCommentThreads(server.url, videoUUID, 0, 5)
|
const res = await getVideoCommentThreads(server.url, videoUUID, 0, 5)
|
||||||
|
|
||||||
expect(res.body.total).to.equal(1)
|
expect(res.body.total).to.equal(1)
|
||||||
|
expect(res.body.totalNotDeletedComments).to.equal(1)
|
||||||
expect(res.body.data).to.be.an('array')
|
expect(res.body.data).to.be.an('array')
|
||||||
expect(res.body.data).to.have.lengthOf(1)
|
expect(res.body.data).to.have.lengthOf(1)
|
||||||
|
|
||||||
|
@ -172,6 +174,7 @@ describe('Test video comments', function () {
|
||||||
const res = await getVideoCommentThreads(server.url, videoUUID, 0, 5, 'createdAt')
|
const res = await getVideoCommentThreads(server.url, videoUUID, 0, 5, 'createdAt')
|
||||||
|
|
||||||
expect(res.body.total).to.equal(3)
|
expect(res.body.total).to.equal(3)
|
||||||
|
expect(res.body.totalNotDeletedComments).to.equal(6)
|
||||||
expect(res.body.data).to.be.an('array')
|
expect(res.body.data).to.be.an('array')
|
||||||
expect(res.body.data).to.have.lengthOf(3)
|
expect(res.body.data).to.have.lengthOf(3)
|
||||||
|
|
||||||
|
@ -186,26 +189,35 @@ describe('Test video comments', function () {
|
||||||
it('Should delete a reply', async function () {
|
it('Should delete a reply', async function () {
|
||||||
await deleteVideoComment(server.url, server.accessToken, videoId, replyToDeleteId)
|
await deleteVideoComment(server.url, server.accessToken, videoId, replyToDeleteId)
|
||||||
|
|
||||||
const res = await getVideoThreadComments(server.url, videoUUID, threadId)
|
{
|
||||||
|
const res = await getVideoCommentThreads(server.url, videoUUID, 0, 5, 'createdAt')
|
||||||
|
|
||||||
const tree: VideoCommentThreadTree = res.body
|
expect(res.body.total).to.equal(3)
|
||||||
expect(tree.comment.text).equal('my super first comment')
|
expect(res.body.totalNotDeletedComments).to.equal(5)
|
||||||
expect(tree.children).to.have.lengthOf(2)
|
}
|
||||||
|
|
||||||
const firstChild = tree.children[0]
|
{
|
||||||
expect(firstChild.comment.text).to.equal('my super answer to thread 1')
|
const res = await getVideoThreadComments(server.url, videoUUID, threadId)
|
||||||
expect(firstChild.children).to.have.lengthOf(1)
|
|
||||||
|
|
||||||
const childOfFirstChild = firstChild.children[0]
|
const tree: VideoCommentThreadTree = res.body
|
||||||
expect(childOfFirstChild.comment.text).to.equal('my super answer to answer of thread 1')
|
expect(tree.comment.text).equal('my super first comment')
|
||||||
expect(childOfFirstChild.children).to.have.lengthOf(0)
|
expect(tree.children).to.have.lengthOf(2)
|
||||||
|
|
||||||
const deletedChildOfFirstChild = tree.children[1]
|
const firstChild = tree.children[0]
|
||||||
expect(deletedChildOfFirstChild.comment.text).to.equal('')
|
expect(firstChild.comment.text).to.equal('my super answer to thread 1')
|
||||||
expect(deletedChildOfFirstChild.comment.isDeleted).to.be.true
|
expect(firstChild.children).to.have.lengthOf(1)
|
||||||
expect(deletedChildOfFirstChild.comment.deletedAt).to.not.be.null
|
|
||||||
expect(deletedChildOfFirstChild.comment.account).to.be.null
|
const childOfFirstChild = firstChild.children[0]
|
||||||
expect(deletedChildOfFirstChild.children).to.have.lengthOf(0)
|
expect(childOfFirstChild.comment.text).to.equal('my super answer to answer of thread 1')
|
||||||
|
expect(childOfFirstChild.children).to.have.lengthOf(0)
|
||||||
|
|
||||||
|
const deletedChildOfFirstChild = tree.children[1]
|
||||||
|
expect(deletedChildOfFirstChild.comment.text).to.equal('')
|
||||||
|
expect(deletedChildOfFirstChild.comment.isDeleted).to.be.true
|
||||||
|
expect(deletedChildOfFirstChild.comment.deletedAt).to.not.be.null
|
||||||
|
expect(deletedChildOfFirstChild.comment.account).to.be.null
|
||||||
|
expect(deletedChildOfFirstChild.children).to.have.lengthOf(0)
|
||||||
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
it('Should delete a complete thread', async function () {
|
it('Should delete a complete thread', async function () {
|
||||||
|
|
|
@ -2,3 +2,7 @@ export interface ResultList<T> {
|
||||||
total: number
|
total: number
|
||||||
data: T[]
|
data: T[]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface ThreadsResultList <T> extends ResultList <T> {
|
||||||
|
totalNotDeletedComments: number
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue