diff --git a/apps/comments-ui/src/actions.ts b/apps/comments-ui/src/actions.ts index 08ea37a240..09c6b0f736 100644 --- a/apps/comments-ui/src/actions.ts +++ b/apps/comments-ui/src/actions.ts @@ -280,13 +280,13 @@ async function deleteComment({state, api, data: comment}: {state: EditableAppCon }); return { - comments: state.comments.map((c) => { + comments: state.comments.map((topLevelComment) => { // If the comment has replies we want to keep it so the replies are // still visible, but mark the comment as deleted. Otherwise remove it. - if (c.id === comment.id) { - if (c.replies.length > 0) { + if (topLevelComment.id === comment.id) { + if (topLevelComment.replies.length > 0) { return { - ...c, + ...topLevelComment, status: 'deleted' }; } else { @@ -294,11 +294,22 @@ async function deleteComment({state, api, data: comment}: {state: EditableAppCon } } - const updatedReplies = c.replies.filter(r => r.id !== comment.id); - return { - ...c, + const originalLength = topLevelComment.replies.length; + const updatedReplies = topLevelComment.replies.filter(reply => reply.id !== comment.id); + const hasDeletedReply = originalLength !== updatedReplies.length; + + const updatedTopLevelComment = { + ...topLevelComment, replies: updatedReplies }; + + // When a reply is deleted we need to update the parent's count so + // pagination displays the correct number of replies still to load + if (hasDeletedReply && topLevelComment.count?.replies) { + topLevelComment.count.replies = topLevelComment.count.replies - 1; + } + + return updatedTopLevelComment; }).filter(Boolean), commentCount: state.commentCount - 1 }; diff --git a/apps/comments-ui/src/components/content/RepliesPagination.tsx b/apps/comments-ui/src/components/content/RepliesPagination.tsx index 1c8ec8edb8..5b964d3e0d 100644 --- a/apps/comments-ui/src/components/content/RepliesPagination.tsx +++ b/apps/comments-ui/src/components/content/RepliesPagination.tsx @@ -12,7 +12,7 @@ const RepliesPagination: React.FC = ({loadMore, count}) => { const shortText = t('{{amount}} more', {amount: formatNumber(count)}); return ( -
+
diff --git a/apps/comments-ui/test/e2e/actions.test.ts b/apps/comments-ui/test/e2e/actions.test.ts index 0654e81b78..8741389e98 100644 --- a/apps/comments-ui/test/e2e/actions.test.ts +++ b/apps/comments-ui/test/e2e/actions.test.ts @@ -341,6 +341,13 @@ test.describe('Actions', async () => { ); }); + async function deleteComment(page, frame, commentComponent) { + await commentComponent.getByTestId('more-button').first().click(); + await frame.getByTestId('delete').click(); + const popupIframe = page.frameLocator('iframe[title="deletePopup"]'); + await popupIframe.getByTestId('delete-popup-confirm').click(); + } + test('Can delete a comment', async ({page}) => { const loggedInMember = buildMember(); mockedApi.setMember(loggedInMember); @@ -352,15 +359,8 @@ test.describe('Actions', async () => { const {frame} = await initializeTest(page); - const comment = frame.getByTestId('comment-component').nth(0); - const moreButton = comment.getByTestId('more-button').first(); - await moreButton.click(); - await frame.getByTestId('delete').click(); - - const popupIframe = page.frameLocator('iframe[title="deletePopup"]'); - - await expect(popupIframe.getByTestId('delete-popup')).toBeVisible(); - await popupIframe.getByTestId('delete-popup-confirm').click(); + const commentToDelete = frame.getByTestId('comment-component').nth(0); + await deleteComment(page, frame, commentToDelete); await expect(frame.getByTestId('comment-component')).toHaveCount(0); }); @@ -382,20 +382,33 @@ test.describe('Actions', async () => { const {frame} = await initializeTest(page); const comment = frame.getByTestId('comment-component').nth(0); - const reply = comment.getByTestId('comment-component').nth(0); - const moreButton = reply.getByTestId('more-button').first(); - await moreButton.click(); - await frame.getByTestId('delete').click(); - - const popupIframe = page.frameLocator('iframe[title="deletePopup"]'); - - await expect(popupIframe.getByTestId('delete-popup')).toBeVisible(); - await popupIframe.getByTestId('delete-popup-confirm').click(); + const replyToDelete = comment.getByTestId('comment-component').nth(0); + await deleteComment(page, frame, replyToDelete); await expect(frame.getByTestId('comment-component')).toHaveCount(1); await expect(frame.getByTestId('replies-line')).not.toBeVisible(); }); + test('Deleting a reply updates pagination', async ({page}) => { + const loggedInMember = buildMember(); + mockedApi.setMember(loggedInMember); + + mockedApi.addComment({ + html: '

Parent comment

', + // 6 replies + replies: Array.from({length: 6}, (_, i) => buildReply({member: loggedInMember, html: `

Reply ${i + 1}

`})) + }); + + const {frame} = await initializeTest(page); + await expect(frame.getByTestId('replies-pagination')).toContainText('3'); + + const replyToDelete = frame.getByTestId('comment-component').nth(2); + await deleteComment(page, frame, replyToDelete); + + // Replies count does not change - we still have 3 unloaded replies + await expect(frame.getByTestId('replies-pagination')).toContainText('3'); + }); + test('Can delete a comment with replies', async ({page}) => { const loggedInMember = buildMember(); mockedApi.setMember(loggedInMember); @@ -412,22 +425,15 @@ test.describe('Actions', async () => { const {frame} = await initializeTest(page); - const comment = frame.getByTestId('comment-component').nth(0); - const moreButton = comment.getByTestId('more-button').first(); - await moreButton.click(); - await frame.getByTestId('delete').click(); - - const popupIframe = page.frameLocator('iframe[title="deletePopup"]'); - - await expect(popupIframe.getByTestId('delete-popup')).toBeVisible(); - await popupIframe.getByTestId('delete-popup-confirm').click(); + const commentToDelete = frame.getByTestId('comment-component').nth(0); + await deleteComment(page, frame, commentToDelete); await expect(frame.getByTestId('comment-component')).toHaveCount(2); await expect(frame.getByText('This comment has been removed')).toBeVisible(); await expect(frame.getByTestId('replies-line')).toBeVisible(); }); - test.describe('Sorting - flag needs to be enabled', () => { + test.describe('Sorting', () => { test('Renders Sorting Form dropdown', async ({page}) => { mockedApi.addComment({ html: '

This is comment 1

'