0
Fork 0
mirror of https://github.com/TryGhost/Ghost.git synced 2025-01-06 22:40:14 -05:00

Removed link from replied-to ref when deleted/hidden

closes https://linear.app/ghost/issue/PLG-294

- making the `replied to: [removed]` text a link was a bit confusing because clicking it does nothing
- if the replied-to comment doesn't exist (e.g. hidden/deleted and not returned in API response) or has been unpublished we replace the `<a>` with a `<span>` to remove the link behaviour
This commit is contained in:
Kevin Ansfield 2024-12-04 14:38:47 +00:00
parent 0651d7178b
commit 7e60172027
2 changed files with 85 additions and 25 deletions

View file

@ -1,5 +1,6 @@
import {AppContext} from '../../AppContext';
import {CommentComponent} from './Comment';
import {CommentComponent, RepliedToSnippet} from './Comment';
import {buildComment} from '../../../test/utils/fixtures';
import {render, screen} from '@testing-library/react';
const contextualRender = (ui, {appContext, ...renderOptions}) => {
@ -20,23 +21,81 @@ const contextualRender = (ui, {appContext, ...renderOptions}) => {
describe('<CommentComponent>', function () {
it('renders reply-to-reply content', function () {
const appContext = {labs: {commentImprovements: true}};
const parent = {
id: '1',
status: 'published',
count: {likes: 0}
};
const comment = {
id: '3',
status: 'published',
in_reply_to_id: '2',
const reply1 = buildComment({
html: '<p>First reply</p>'
});
const reply2 = buildComment({
in_reply_to_id: reply1.id,
in_reply_to_snippet: 'First reply',
html: '<p>Second reply</p>',
count: {likes: 0}
};
html: '<p>Second reply</p>'
});
const parent = buildComment({
replies: [reply1, reply2]
});
const appContext = {comments: [parent], labs: {commentImprovements: true}};
contextualRender(<CommentComponent comment={comment} parent={parent} />, {appContext});
contextualRender(<CommentComponent comment={reply2} parent={parent} />, {appContext});
expect(screen.getByText('First reply')).toBeInTheDocument();
});
});
describe('<RepliedToSnippet>', function () {
it('renders a link when replied-to comment is published', function () {
const reply1 = buildComment({
html: '<p>First reply</p>'
});
const reply2 = buildComment({
in_reply_to_id: reply1.id,
in_reply_to_snippet: 'First reply',
html: '<p>Second reply</p>'
});
const parent = buildComment({
replies: [reply1, reply2]
});
const appContext = {comments: [parent], labs: {commentImprovements: true}};
contextualRender(<RepliedToSnippet comment={reply2} />, {appContext});
const element = screen.getByTestId('comment-in-reply-to');
expect(element).toBeInstanceOf(HTMLAnchorElement);
});
it('does not render a link when replied-to comment is deleted', function () {
const reply1 = buildComment({
html: '<p>First reply</p>',
status: 'deleted'
});
const reply2 = buildComment({
in_reply_to_id: reply1.id,
in_reply_to_snippet: 'First reply',
html: '<p>Second reply</p>'
});
const parent = buildComment({
replies: [reply1, reply2]
});
const appContext = {comments: [parent], labs: {commentImprovements: true}};
contextualRender(<RepliedToSnippet comment={reply2} />, {appContext});
const element = screen.getByTestId('comment-in-reply-to');
expect(element).toBeInstanceOf(HTMLSpanElement);
});
it('does not render a link when replied-to comment is missing (i.e. removed)', function () {
const reply2 = buildComment({
in_reply_to_id: 'missing',
in_reply_to_snippet: 'First reply',
html: '<p>Second reply</p>'
});
const parent = buildComment({
replies: [reply2]
});
const appContext = {comments: [parent], labs: {commentImprovements: true}};
contextualRender(<RepliedToSnippet comment={reply2} />, {appContext});
const element = screen.getByTestId('comment-in-reply-to');
expect(element).toBeInstanceOf(HTMLSpanElement);
});
});

View file

@ -279,7 +279,7 @@ const AuthorName: React.FC<{comment: Comment}> = ({comment}) => {
);
};
const RepliedToSnippet: React.FC<{comment: Comment}> = ({comment}) => {
export const RepliedToSnippet: React.FC<{comment: Comment}> = ({comment}) => {
const {comments, dispatchAction, t} = useAppContext();
const inReplyToComment = findCommentById(comments, comment.in_reply_to_id);
@ -298,19 +298,20 @@ const RepliedToSnippet: React.FC<{comment: Comment}> = ({comment}) => {
};
let inReplyToSnippet = comment.in_reply_to_snippet;
if (inReplyToComment && inReplyToComment.status !== 'published') {
// For public API requests hidden/deleted comments won't exist in the comments array
// unless it was only just deleted in which case it will exist but have a 'deleted' status
if (!inReplyToComment || inReplyToComment.status !== 'published') {
inReplyToSnippet = `[${t('removed')}]`;
}
const linkToReply = inReplyToComment && inReplyToComment.status === 'published';
const className = 'font-semibold text-neutral-900/60 transition-colors hover:text-neutral-900/70 dark:text-white/70 dark:hover:text-white/80';
return (
<a
className="font-semibold text-neutral-900/60 transition-colors hover:text-neutral-900/70 dark:text-white/70 dark:hover:text-white/80"
data-testid="comment-in-reply-to"
href={`#${comment.in_reply_to_id}`}
onClick={scrollRepliedToCommentIntoView}
>
{inReplyToSnippet}
</a>
linkToReply
? <a className={className} data-testid="comment-in-reply-to" href={`#${comment.in_reply_to_id}`} onClick={scrollRepliedToCommentIntoView}>{inReplyToSnippet}</a>
: <span className={className} data-testid="comment-in-reply-to">{inReplyToSnippet}</span>
);
};