diff --git a/src/components/challenge-modal/__tests__/challenge-modal.test.tsx b/src/components/challenge-modal/__tests__/challenge-modal.test.tsx index 59f09b0a..7f591731 100644 --- a/src/components/challenge-modal/__tests__/challenge-modal.test.tsx +++ b/src/components/challenge-modal/__tests__/challenge-modal.test.tsx @@ -49,11 +49,15 @@ vi.mock('@bitsocial/bitsocial-react-hooks', () => ({ useComment: ({ commentCid }: { commentCid?: string }) => (commentCid ? testState.commentsByCid[commentCid] : undefined), })); -vi.mock('../../../lib/utils/challenge-utils', () => ({ - getPublicationPreview: () => testState.publicationPreview, - getPublicationType: () => testState.publicationType, - getVotePreview: () => testState.votePreview, -})); +vi.mock('../../../lib/utils/challenge-utils', async (importOriginal) => { + const actual = await importOriginal(); + return { + ...actual, + getPublicationPreview: () => testState.publicationPreview, + getPublicationType: () => testState.publicationType, + getVotePreview: () => testState.votePreview, + }; +}); vi.mock('../../../hooks/use-is-mobile', () => ({ default: () => testState.isMobile, @@ -224,7 +228,7 @@ describe('ChallengeModal', () => { input?.dispatchEvent(new KeyboardEvent('keydown', { bubbles: true, key: 'Enter' })); }); - expect(publication.publishChallengeAnswers).toHaveBeenCalledWith(['4']); + expect(publication.publishChallengeAnswers).toHaveBeenCalledWith({ challengeAnswers: ['4'] }); expect(testState.removeChallengeMock).toHaveBeenCalledOnce(); }); @@ -310,7 +314,7 @@ describe('ChallengeModal', () => { await dispatchInput(container.querySelector('input[placeholder*="TYPE THE ANSWER HERE"]') as HTMLInputElement, 'step two'); await clickButton('submit'); - expect(publication.publishChallengeAnswers).toHaveBeenCalledWith(['step one', 'step two']); + expect(publication.publishChallengeAnswers).toHaveBeenCalledWith({ challengeAnswers: ['step one', 'step two'] }); expect(testState.removeChallengeMock).toHaveBeenCalledOnce(); }); @@ -369,7 +373,7 @@ describe('ChallengeModal', () => { expect(doneButton?.getAttribute('aria-label')).toBe('Finish challenge'); await clickButton('Finish Challenge'); - expect(publication.publishChallengeAnswers).toHaveBeenCalledWith(['']); + expect(publication.publishChallengeAnswers).toHaveBeenCalledWith({ challengeAnswers: [''] }); expect(testState.removeChallengeMock).toHaveBeenCalledOnce(); }); @@ -481,7 +485,7 @@ describe('ChallengeModal', () => { ); }); - expect(publication.publishChallengeAnswers).toHaveBeenCalledWith(['']); + expect(publication.publishChallengeAnswers).toHaveBeenCalledWith({ challengeAnswers: [''] }); expect(testState.removeChallengeMock).toHaveBeenCalledOnce(); }); @@ -538,7 +542,7 @@ describe('ChallengeModal', () => { ); }); - expect(publication.publishChallengeAnswers).toHaveBeenCalledWith(['', '']); + expect(publication.publishChallengeAnswers).toHaveBeenCalledWith({ challengeAnswers: ['', ''] }); expect(testState.removeChallengeMock).toHaveBeenCalledOnce(); }); diff --git a/src/components/challenge-modal/challenge-modal.tsx b/src/components/challenge-modal/challenge-modal.tsx index 05be1845..2afa6d27 100644 --- a/src/components/challenge-modal/challenge-modal.tsx +++ b/src/components/challenge-modal/challenge-modal.tsx @@ -1,7 +1,7 @@ import { useRef, useState, useEffect, useCallback } from 'react'; import { useTranslation } from 'react-i18next'; import { Challenge as ChallengeType, useAccount, useComment } from '@bitsocial/bitsocial-react-hooks'; -import { getPublicationPreview, getPublicationType, getVotePreview } from '../../lib/utils/challenge-utils'; +import { getPublicationPreview, getPublicationType, getVotePreview, publishPublicationChallengeAnswers } from '../../lib/utils/challenge-utils'; import { stripGeneratedFortuneMarkup } from '../../lib/utils/post-options-utils'; import useIsMobile from '../../hooks/use-is-mobile'; import useChallengesStore from '../../stores/use-challenges-store'; @@ -40,6 +40,10 @@ const ImageChallenge = ({ challenge }: { challenge: string }) =>
Invalid image challenge
); +const logPublishChallengeAnswersError = (error: unknown) => { + console.error('Failed to publish challenge answers:', error); +}; + const isLocalIframeHostname = (hostname: string) => hostname === 'localhost' || hostname === '127.0.0.1' || hostname === '[::1]' || hostname.endsWith('.localhost'); type ValidatedIframeUrl = { status: 'valid'; finalUrl: string; origin: string } | { status: 'invalid'; error: unknown } | { status: 'unsupported' }; @@ -391,7 +395,7 @@ const Challenge = ({ challenge, closeModal, abandonModal }: ChallengeProps) => { const onSubmit = () => { if (!publication) return; - publication.publishChallengeAnswers(answers); + void publishPublicationChallengeAnswers(publication, answers).catch(logPublishChallengeAnswersError); setAnswers([]); closeModal(); }; @@ -413,7 +417,7 @@ const Challenge = ({ challenge, closeModal, abandonModal }: ChallengeProps) => { return; } - publication.publishChallengeAnswers(updatedAnswers); + void publishPublicationChallengeAnswers(publication, updatedAnswers).catch(logPublishChallengeAnswersError); setAnswers([]); closeModal(); }, diff --git a/src/lib/utils/challenge-utils.ts b/src/lib/utils/challenge-utils.ts index 75797da4..264aec27 100644 --- a/src/lib/utils/challenge-utils.ts +++ b/src/lib/utils/challenge-utils.ts @@ -13,19 +13,28 @@ const resolveBoardIdentifier = (communityAddress: unknown): string => { return boardPath === communityAddress ? communityAddress : `/${boardPath}/`; }; -export type ChallengePublication = Partial & { +type ChallengeAnswersInput = string[] | { challengeAnswers?: string[] }; + +export type ChallengePublication = Partial> & { author?: unknown; commentCid?: string; communityAddress?: string; content?: string; link?: string; parentCid?: string; + publishChallengeAnswers?: (challengeAnswers?: ChallengeAnswersInput) => Promise | void; shortCommunityAddress?: string; subplebbitAddress?: string; title?: string; vote?: number; }; +export const publishPublicationChallengeAnswers = async (publication: ChallengePublication | undefined, challengeAnswers: string[]) => { + const publishChallengeAnswers = publication?.publishChallengeAnswers; + if (typeof publishChallengeAnswers !== 'function') return; + await publishChallengeAnswers.call(publication, { challengeAnswers }); +}; + export const redactGeneratedFortuneFromPublication = (publication: T): T => { if (!publication || typeof publication !== 'object') { return publication;