fix(pending posts): show publish errors

This commit is contained in:
Tommaso Casaburi
2026-04-20 16:15:12 +07:00
parent b196670cda
commit 338f415f2a
5 changed files with 100 additions and 4 deletions
@@ -22,6 +22,8 @@ type TestComment = {
edit?: {
timestamp: number;
};
error?: unknown;
errors?: unknown[];
number?: number;
original?: {
content?: string;
@@ -126,6 +128,19 @@ vi.mock('../../loading-ellipsis', () => ({
default: ({ string }: { string: string }) => createElement('span', { 'data-testid': 'loading-ellipsis' }, string),
}));
vi.mock('../../error-display/error-display', () => ({
default: ({ error, inline, showImmediately }: { error?: Error; inline?: boolean; showImmediately?: boolean }) =>
createElement(
'button',
{
'data-testid': 'error-display',
'data-inline': String(Boolean(inline)),
'data-show-immediately': String(Boolean(showImmediately)),
},
error?.message || String(error),
),
}));
vi.mock('../../reply-quote-preview', () => ({
default: ({
isOP,
@@ -393,4 +408,20 @@ describe('CommentContent', () => {
});
expect(container.querySelector('[data-testid="loading-ellipsis"]')?.textContent).toBe('Publishing');
});
it('renders failed unpublished comment errors through ErrorDisplay', async () => {
testState.stateString = 'Failed';
await renderContent({
content: 'still pending',
errors: [new Error('spam blocker server error')],
postCid: 'post-2',
state: 'failed',
});
const errorDisplay = container.querySelector('[data-testid="error-display"]');
expect(errorDisplay?.textContent).toBe('spam blocker server error');
expect(errorDisplay?.getAttribute('data-inline')).toBe('true');
expect(errorDisplay?.getAttribute('data-show-immediately')).toBe('true');
expect(container.querySelector('[data-testid="loading-ellipsis"]')).toBeNull();
});
});
@@ -11,6 +11,7 @@ import { isPostPageView } from '../../lib/utils/view-utils';
import useIsMobile from '../../hooks/use-is-mobile';
import useStateString from '../../hooks/use-state-string';
import LoadingEllipsis from '../../components/loading-ellipsis';
import ErrorDisplay from '../../components/error-display/error-display';
import ReplyQuotePreview from '../../components/reply-quote-preview';
import Markdown from '../../components/markdown';
import Tooltip from '../../components/tooltip';
@@ -63,6 +64,12 @@ const useScopedCidToNumber = (cids: string[]) => {
return cidToNumber;
};
const getFailedCommentError = (comment: Comment | undefined): unknown => {
if (comment?.state !== 'failed') return undefined;
if (comment.error) return comment.error;
return Array.isArray(comment.errors) ? comment.errors.find(Boolean) : undefined;
};
const CommentContent = ({ comment: post, prependContent }: { comment: Comment; prependContent?: ReactNode }) => {
const { t } = useTranslation();
const params = useParams();
@@ -123,9 +130,18 @@ const CommentContent = ({ comment: post, prependContent }: { comment: Comment; p
const stateString = useStateString(resolvedPost);
const hasFailedState = state === 'failed';
const failedError = getFailedCommentError(resolvedPost);
const loadingString = (
<div className={styles.stateString}>{!hasFailedState ? <LoadingEllipsis string={stateString || t('loading')} /> : stateString || capitalize(t('failed'))}</div>
<div className={styles.stateString}>
{failedError ? (
<ErrorDisplay error={failedError} inline={true} showImmediately={true} />
) : !hasFailedState ? (
<LoadingEllipsis string={stateString || t('loading')} />
) : (
stateString || capitalize(t('failed'))
)}
</div>
);
return (