diff --git a/ghost/core/core/server/services/comments/CommentsController.js b/ghost/core/core/server/services/comments/CommentsController.js index 7e4e47971a..40baef493c 100644 --- a/ghost/core/core/server/services/comments/CommentsController.js +++ b/ghost/core/core/server/services/comments/CommentsController.js @@ -87,6 +87,7 @@ module.exports = class CommentsController { */ async adminReplies(frame) { frame.options.isAdmin = true; + frame.options.order = 'created_at asc'; // we always want to load replies from oldest to newest return this.service.getReplies(frame.options.id, _.omit(frame.options, 'id')); } diff --git a/ghost/core/test/e2e-api/admin/comments.test.js b/ghost/core/test/e2e-api/admin/comments.test.js index b2f2e75894..01858ae172 100644 --- a/ghost/core/test/e2e-api/admin/comments.test.js +++ b/ghost/core/test/e2e-api/admin/comments.test.js @@ -14,6 +14,7 @@ const dbFns = { * @property {string} [parent_id] * @property {string} [html='This is a comment'] * @property {string} [status='published'] + * @property {date} [created_at] */ /** * @typedef {Object} AddCommentReplyData @@ -55,7 +56,8 @@ const dbFns = { member_id: reply.member_id, parent_id: parent.get('id'), html: reply.html || '
This is a reply
', - status: reply.status || 'published' + status: reply.status || 'published', + created_at: reply.created_at || new Date() }); createdReplies.push(createdReply); } @@ -455,5 +457,64 @@ describe('Admin Comments API', function () { assert.equal(res2.body.comments.length, 1); assert.equal(res2.body.comments[0].html, 'Reply 4'); }); + + it('ensure replies are always ordered from oldest to newest', async function () { + const post = fixtureManager.get('posts', 1); + const {parent} = await dbFns.addCommentWithReplies({ + member_id: fixtureManager.get('members', 0).id, + post_id: post.id, + html: 'Comment 1', + status: 'published', + created_at: new Date('2021-01-01'), + replies: [ + { + member_id: fixtureManager.get('members', 0).id, + html: 'Reply 1', + status: 'published', + created_at: new Date('2022-01-01') + }, + { + member_id: fixtureManager.get('members', 0).id, + html: 'Reply 2', + status: 'published', + created_at: new Date('2022-01-02') + }, + { + member_id: fixtureManager.get('members', 0).id, + html: 'Reply 3', + status: 'hidden', + created_at: new Date('2022-01-03') + }, + { + member_id: fixtureManager.get('members', 0).id, + html: 'Reply 4', + status: 'hidden', + created_at: new Date('2022-01-04') + }, + { + member_id: fixtureManager.get('members', 0).id, + html: 'Reply 5', + status: 'published', + created_at: new Date('2022-01-05') + }, + { + member_id: fixtureManager.get('members', 0).id, + html: 'Reply 6', + status: 'published', + created_at: new Date('2022-01-06') + } + ] + }); + + const res = await adminApi.get('/comments/post/' + post.id + '/'); + const item = res.body.comments.find(cmt => parent.id === cmt.id); + const lastReply = item.replies[item.replies.length - 1]; + const filter = encodeURIComponent(`id:>'${lastReply.id}'`); + const res2 = await adminApi.get(`/comments/${parent.id}/replies?limit=10&filter=${filter}`); + assert.equal(res2.body.comments.length, 3); + assert.equal(res2.body.comments[0].html, 'Reply 4'); + assert.equal(res2.body.comments[1].html, 'Reply 5'); + assert.equal(res2.body.comments[2].html, 'Reply 6'); + }); }); });