mirror of
https://github.com/bitsocialnet/5chan.git
synced 2026-08-03 07:41:04 +02:00
fix(challenge-modal): publish challenge answers with pkc object schema
pkc-js's publishChallengeAnswers destructures { challengeAnswers } from its
argument, so passing a bare string[] left challengeAnswers undefined and
silently broke challenge submission (i.e. posting). Wrap answers in the object
form via a publishPublicationChallengeAnswers helper with error logging, and
align the ChallengePublication type with the real runtime signature.
This commit is contained in:
@@ -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<typeof import('../../../lib/utils/challenge-utils')>();
|
||||
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<HTMLInputElement>('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();
|
||||
});
|
||||
|
||||
|
||||
@@ -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 }) =>
|
||||
<div className={styles.challengeMedia}>Invalid image challenge</div>
|
||||
);
|
||||
|
||||
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();
|
||||
},
|
||||
|
||||
@@ -13,19 +13,28 @@ const resolveBoardIdentifier = (communityAddress: unknown): string => {
|
||||
return boardPath === communityAddress ? communityAddress : `/${boardPath}/`;
|
||||
};
|
||||
|
||||
export type ChallengePublication = Partial<Comment> & {
|
||||
type ChallengeAnswersInput = string[] | { challengeAnswers?: string[] };
|
||||
|
||||
export type ChallengePublication = Partial<Omit<Comment, 'publishChallengeAnswers'>> & {
|
||||
author?: unknown;
|
||||
commentCid?: string;
|
||||
communityAddress?: string;
|
||||
content?: string;
|
||||
link?: string;
|
||||
parentCid?: string;
|
||||
publishChallengeAnswers?: (challengeAnswers?: ChallengeAnswersInput) => Promise<void> | 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 = <T>(publication: T): T => {
|
||||
if (!publication || typeof publication !== 'object') {
|
||||
return publication;
|
||||
|
||||
Reference in New Issue
Block a user