fix(pending posts): clean up failed post display

This commit is contained in:
Tommaso Casaburi
2026-04-30 17:39:06 +07:00
parent e6096fd989
commit 5c74a1e495
6 changed files with 45 additions and 16 deletions
@@ -14,9 +14,14 @@ const testState = vi.hoisted(() => ({
alertMock: vi.fn(),
deleteCommentMock: vi.fn(async (_targetComment: string | number) => undefined),
lastPublishOptions: undefined as Record<string, any> | undefined,
navigateMock: vi.fn(),
publishCommentMock: vi.fn(async () => undefined),
}));
vi.mock('react-router-dom', () => ({
useNavigate: () => testState.navigateMock,
}));
vi.mock('@bitsocial/bitsocial-react-hooks', () => ({
deleteComment: (targetComment: string | number) => testState.deleteCommentMock(targetComment),
usePublishComment: (options: Record<string, any> | undefined) => {
@@ -63,14 +68,14 @@ const failedPost = {
title: 'Hello',
};
const HookHarness = ({ post }: { post: typeof failedPost }) => {
latestValue = useDeleteFailedPost(post);
const HookHarness = ({ deleteRedirectPath, post }: { deleteRedirectPath?: string; post: typeof failedPost }) => {
latestValue = useDeleteFailedPost(post, deleteRedirectPath);
return null;
};
const renderHook = (post = failedPost) => {
const renderHook = (post = failedPost, deleteRedirectPath?: string) => {
act(() => {
root.render(createElement(HookHarness, { post }));
root.render(createElement(HookHarness, { deleteRedirectPath, post }));
});
};
@@ -137,6 +142,17 @@ describe('useDeleteFailedPost', () => {
expect(testState.publishCommentMock).toHaveBeenCalledTimes(1);
});
it('redirects after deleting a failed post when a redirect path is provided', async () => {
renderHook(failedPost, '/mu');
await act(async () => {
await latestValue.onDeleteFailedPost();
});
expect(testState.deleteCommentMock).toHaveBeenCalledWith('failed-cid');
expect(testState.navigateMock).toHaveBeenCalledWith('/mu', { replace: true });
});
it('routes retry challenges through the challenge store and preserves abandon behavior', async () => {
await act(async () => {
await testState.lastPublishOptions?.onChallenge('captcha', 'nonce');
+7 -2
View File
@@ -1,4 +1,5 @@
import { useCallback, useMemo, useRef, useState } from 'react';
import { useNavigate } from 'react-router-dom';
import { ChallengeVerification, Comment, PublishCommentOptions, deleteComment, usePublishComment } from '@bitsocial/bitsocial-react-hooks';
import { alertChallengeVerificationFailed } from '../lib/utils/challenge-utils';
import useChallengesStore from '../stores/use-challenges-store';
@@ -67,10 +68,11 @@ export const getFailedPostRetryPublishOptions = (post?: FailedPost): PublishComm
return retryOptions;
};
const useDeleteFailedPost = (post?: FailedPost) => {
const useDeleteFailedPost = (post?: FailedPost, deleteRedirectPath?: string) => {
const [isDeletingFailedPost, setIsDeletingFailedPost] = useState(false);
const [isRetryingFailedPost, setIsRetryingFailedPost] = useState(false);
const addChallenge = useChallengesStore((state) => state.addChallenge);
const navigate = useNavigate();
const abandonPublishRef = useRef<(() => Promise<void>) | undefined>();
const abandonCurrentPublish = useCallback(async () => {
await abandonPublishRef.current?.();
@@ -114,13 +116,16 @@ const useDeleteFailedPost = (post?: FailedPost) => {
deleteComment(targetComment)
.then(() => {
setIsDeletingFailedPost(false);
if (deleteRedirectPath) {
navigate(deleteRedirectPath, { replace: true });
}
})
.catch((error) => {
console.error('Failed to delete failed post:', error);
alert(`Failed to delete post: ${error instanceof Error ? error.message : 'Unknown error'}`);
setIsDeletingFailedPost(false);
});
}, [canDeleteFailedPost, isDeletingFailedPost, isRetryingFailedPost, post]);
}, [canDeleteFailedPost, deleteRedirectPath, isDeletingFailedPost, isRetryingFailedPost, navigate, post]);
const canRetryFailedPost = canDeleteFailedPost && Boolean(retryPublishOptions);