mirror of
https://github.com/bitsocialnet/5chan.git
synced 2026-08-03 07:41:04 +02:00
fix(challenge): support pkc spam blocker flow
This commit is contained in:
@@ -3,6 +3,7 @@ import { createElement } from 'react';
|
||||
import { createRoot, type Root } from 'react-dom/client';
|
||||
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
|
||||
import ChallengeModal from '../challenge-modal';
|
||||
import getShortAddress from '../../../lib/get-short-address';
|
||||
|
||||
(globalThis as { IS_REACT_ACT_ENVIRONMENT?: boolean }).IS_REACT_ACT_ENVIRONMENT = true;
|
||||
const act = (React as { act?: (cb: () => void | Promise<void>) => void | Promise<void> }).act as (cb: () => void | Promise<void>) => void | Promise<void>;
|
||||
@@ -88,7 +89,7 @@ let consoleErrorSpy: ReturnType<typeof vi.spyOn>;
|
||||
let postMessageMock: ReturnType<typeof vi.fn>;
|
||||
let root: Root;
|
||||
|
||||
const createPublication = () => ({
|
||||
const createPublication = (): Record<string, any> => ({
|
||||
author: { displayName: 'Alice' },
|
||||
content: 'Publication content',
|
||||
link: 'https://example.com/link',
|
||||
@@ -285,6 +286,63 @@ describe('ChallengeModal', () => {
|
||||
expect(testState.removeChallengeMock).toHaveBeenCalledOnce();
|
||||
});
|
||||
|
||||
it('allows localhost http iframe challenges for local spam blocker testing', async () => {
|
||||
const publication = createPublication();
|
||||
testState.challenges = [
|
||||
createStoredChallenge(
|
||||
{
|
||||
challenge: 'http://localhost:3000/api/v1/iframe/session-123?foo=bar',
|
||||
type: 'url/iframe',
|
||||
},
|
||||
publication,
|
||||
),
|
||||
];
|
||||
|
||||
await renderModal();
|
||||
expect(container.textContent).toContain('mu wants to open localhost:3000');
|
||||
|
||||
await clickButton('Open');
|
||||
|
||||
const iframe = container.querySelector('iframe');
|
||||
expect(iframe).not.toBeNull();
|
||||
expect(iframe?.getAttribute('src')).toContain('http://localhost:3000/api/v1/iframe/session-123?foo=bar&theme=dark');
|
||||
|
||||
await act(async () => {
|
||||
iframe?.dispatchEvent(new Event('load', { bubbles: true }));
|
||||
});
|
||||
|
||||
expect(postMessageMock).toHaveBeenCalledWith(
|
||||
{
|
||||
source: 'plebbit-5chan',
|
||||
theme: 'dark',
|
||||
type: 'plebbit-theme',
|
||||
},
|
||||
'http://localhost:3000',
|
||||
);
|
||||
});
|
||||
|
||||
it('uses the shortened community address when shortCommunityAddress is unavailable', async () => {
|
||||
const longCommunityAddress = '12D3KooWS6yKc5N7o6JcAYHZpaQwAwyh1VddYatarU75Se3HXEeD';
|
||||
const publication = {
|
||||
...createPublication(),
|
||||
shortCommunityAddress: undefined,
|
||||
communityAddress: longCommunityAddress,
|
||||
};
|
||||
testState.challenges = [
|
||||
createStoredChallenge(
|
||||
{
|
||||
challenge: 'http://localhost:3000/api/v1/iframe/session-123?foo=bar',
|
||||
type: 'url/iframe',
|
||||
},
|
||||
publication,
|
||||
),
|
||||
];
|
||||
|
||||
await renderModal();
|
||||
expect(container.textContent).toContain(`${getShortAddress(longCommunityAddress)} wants to open localhost:3000`);
|
||||
expect(container.textContent).not.toContain(`${longCommunityAddress} wants to open localhost:3000`);
|
||||
});
|
||||
|
||||
it('alerts when iframe challenges need a signer address and the account is missing one', async () => {
|
||||
testState.account = { author: { address: '' } };
|
||||
testState.challenges = [
|
||||
|
||||
@@ -9,6 +9,7 @@ import styles from './challenge-modal.module.css';
|
||||
import capitalize from 'lodash/capitalize';
|
||||
import { useSpring, animated } from '@react-spring/web';
|
||||
import { useDrag } from '@use-gesture/react';
|
||||
import getShortAddress from '../../lib/get-short-address';
|
||||
|
||||
const useParentAddress = (parentCid?: string) => {
|
||||
const parentComment = useComment({ commentCid: parentCid, onlyIfCached: true });
|
||||
@@ -25,6 +26,17 @@ const TextChallenge = ({ challenge }: { challenge: string }) => <div className={
|
||||
|
||||
const ImageChallenge = ({ challenge }: { challenge: string }) => <img alt='' className={styles.challengeMedia} src={`data:image/png;base64,${challenge}`} />;
|
||||
|
||||
const isLocalIframeHostname = (hostname: string) => hostname === 'localhost' || hostname === '127.0.0.1' || hostname === '[::1]' || hostname.endsWith('.localhost');
|
||||
|
||||
const getReadableIframeUrl = (challengeUrl: string) => {
|
||||
try {
|
||||
const url = new URL(challengeUrl);
|
||||
return url.host || url.hostname;
|
||||
} catch {
|
||||
return '';
|
||||
}
|
||||
};
|
||||
|
||||
interface IframeChallengeProps {
|
||||
challenge: string;
|
||||
shortCommunityAddress?: string;
|
||||
@@ -42,6 +54,7 @@ const IframeChallenge = ({ challenge, shortCommunityAddress, communityAddress, r
|
||||
const [iframeUrlState, setIframeUrl] = useState('');
|
||||
const [iframeOrigin, setIframeOrigin] = useState('');
|
||||
const iframeRef = useRef<HTMLIFrameElement>(null);
|
||||
const displayCommunityAddress = shortCommunityAddress || (communityAddress ? getShortAddress(communityAddress) : '') || communityAddress || 'unknown board';
|
||||
|
||||
const handleLoadIframe = useCallback(() => {
|
||||
const iframeUrl = challenge;
|
||||
@@ -60,8 +73,10 @@ const IframeChallenge = ({ challenge, shortCommunityAddress, communityAddress, r
|
||||
|
||||
try {
|
||||
const validatedUrl = new URL(replacedUrl);
|
||||
if (validatedUrl.protocol !== 'https:') {
|
||||
throw new Error('Only HTTPS iframe challenges are supported');
|
||||
const isHttps = validatedUrl.protocol === 'https:';
|
||||
const isLocalHttp = validatedUrl.protocol === 'http:' && isLocalIframeHostname(validatedUrl.hostname);
|
||||
if (!isHttps && !isLocalHttp) {
|
||||
throw new Error('Only HTTPS iframe challenges or localhost HTTP challenges are supported');
|
||||
}
|
||||
validatedUrl.pathname = validatedUrl.pathname.replace(/\/{2,}/g, '/');
|
||||
validatedUrl.searchParams.set('theme', theme);
|
||||
@@ -101,7 +116,7 @@ const IframeChallenge = ({ challenge, shortCommunityAddress, communityAddress, r
|
||||
{publicationDetails}
|
||||
<div className={styles.challengeMediaWrapper}>
|
||||
<div className={`${styles.challengeMedia} ${styles.iframeChallengeWarning}`}>
|
||||
{shortCommunityAddress || communityAddress || 'unknown board'} wants to open {readableUrl || 'an external site'}
|
||||
{displayCommunityAddress} wants to open {readableUrl || 'an external site'}
|
||||
</div>
|
||||
</div>
|
||||
<div className={`${styles.challengeFooter} ${styles.iframeFooter}`}>
|
||||
@@ -235,26 +250,11 @@ const Challenge = ({ challenge, closeModal, abandonModal }: ChallengeProps) => {
|
||||
}, [abandonModal]);
|
||||
|
||||
const getChallengeUrl = useCallback(() => {
|
||||
try {
|
||||
const iframeUrl = currentChallenge?.challenge;
|
||||
if (!iframeUrl) return '';
|
||||
const url = new URL(iframeUrl);
|
||||
if (url.hostname === 'mintpass.org') return url.hostname;
|
||||
return url.href;
|
||||
} catch {
|
||||
return '';
|
||||
}
|
||||
const iframeUrl = currentChallenge?.challenge;
|
||||
if (!iframeUrl) return '';
|
||||
return getReadableIframeUrl(iframeUrl);
|
||||
}, [currentChallenge]);
|
||||
|
||||
const readableUrl = (() => {
|
||||
const url = getChallengeUrl();
|
||||
if (!url) return '';
|
||||
try {
|
||||
return decodeURIComponent(url);
|
||||
} catch {
|
||||
return url;
|
||||
}
|
||||
})();
|
||||
const readableUrl = getChallengeUrl();
|
||||
|
||||
if (!challenges?.length || !publication || !currentChallenge) {
|
||||
return null;
|
||||
|
||||
+28
-28
@@ -9,20 +9,20 @@ const act = (React as { act?: (cb: () => void | Promise<void>) => void | Promise
|
||||
const testState = vi.hoisted(() => ({
|
||||
account: {
|
||||
mediaIpfsGatewayUrl: 'https://media.old.example',
|
||||
plebbitOptions: {
|
||||
chainProviders: {
|
||||
eth: { chainId: 1, urls: ['https://eth.old.example'] },
|
||||
sol: { chainId: 101, urls: ['https://sol.old.example'] },
|
||||
},
|
||||
chainProviders: {
|
||||
eth: { chainId: 1, urls: ['https://eth.old.example'] },
|
||||
sol: { chainId: 101, urls: ['https://sol.old.example'] },
|
||||
},
|
||||
pkcOptions: {
|
||||
httpRoutersOptions: ['https://router.old.example'],
|
||||
ipfsGatewayUrls: ['https://ipfs.old.example'],
|
||||
plebbitRpcClientsOptions: ['ws://old.example/key'],
|
||||
pubsubHttpClientsOptions: ['https://pubsub.old.example'],
|
||||
pkcRpcClientsOptions: ['ws://old.example/key'],
|
||||
pubsubKuboRpcClientsOptions: ['https://pubsub.old.example'],
|
||||
},
|
||||
} as Record<string, any>,
|
||||
rpcSettings: {
|
||||
plebbitRpcSettings: {
|
||||
plebbitOptions: {
|
||||
pkcRpcSettings: {
|
||||
pkcOptions: {
|
||||
dataPath: '/tmp/plebbit-data',
|
||||
},
|
||||
},
|
||||
@@ -40,7 +40,7 @@ vi.mock('react-i18next', () => ({
|
||||
vi.mock('@bitsocialnet/bitsocial-react-hooks', () => ({
|
||||
setAccount: (account: unknown) => testState.setAccountMock(account),
|
||||
useAccount: () => testState.account,
|
||||
usePlebbitRpcSettings: () => testState.rpcSettings,
|
||||
usePkcRpcSettings: () => testState.rpcSettings,
|
||||
}));
|
||||
|
||||
let alertSpy: ReturnType<typeof vi.spyOn>;
|
||||
@@ -86,20 +86,20 @@ describe('AdvancedSettings', () => {
|
||||
vi.clearAllMocks();
|
||||
testState.account = {
|
||||
mediaIpfsGatewayUrl: 'https://media.old.example',
|
||||
plebbitOptions: {
|
||||
chainProviders: {
|
||||
eth: { chainId: 1, urls: ['https://eth.old.example'] },
|
||||
sol: { chainId: 101, urls: ['https://sol.old.example'] },
|
||||
},
|
||||
chainProviders: {
|
||||
eth: { chainId: 1, urls: ['https://eth.old.example'] },
|
||||
sol: { chainId: 101, urls: ['https://sol.old.example'] },
|
||||
},
|
||||
pkcOptions: {
|
||||
httpRoutersOptions: ['https://router.old.example'],
|
||||
ipfsGatewayUrls: ['https://ipfs.old.example'],
|
||||
plebbitRpcClientsOptions: ['ws://old.example/key'],
|
||||
pubsubHttpClientsOptions: ['https://pubsub.old.example'],
|
||||
pkcRpcClientsOptions: ['ws://old.example/key'],
|
||||
pubsubKuboRpcClientsOptions: ['https://pubsub.old.example'],
|
||||
},
|
||||
};
|
||||
testState.rpcSettings = {
|
||||
plebbitRpcSettings: {
|
||||
plebbitOptions: {
|
||||
pkcRpcSettings: {
|
||||
pkcOptions: {
|
||||
dataPath: '/tmp/plebbit-data',
|
||||
},
|
||||
},
|
||||
@@ -154,16 +154,16 @@ describe('AdvancedSettings', () => {
|
||||
|
||||
expect(testState.setAccountMock).toHaveBeenCalledWith({
|
||||
mediaIpfsGatewayUrl: 'https://media.new.example',
|
||||
plebbitOptions: {
|
||||
chainProviders: {
|
||||
eth: { chainId: 1, urls: ['https://eth.one.example'] },
|
||||
sol: { chainId: 101, urls: ['https://sol.one.example'] },
|
||||
},
|
||||
chainProviders: {
|
||||
eth: { chainId: 1, urls: ['https://eth.one.example'] },
|
||||
sol: { chainId: 101, urls: ['https://sol.one.example'] },
|
||||
},
|
||||
pkcOptions: {
|
||||
dataPath: '/tmp/next-plebbit',
|
||||
httpRoutersOptions: ['https://router.one.example'],
|
||||
ipfsGatewayUrls: ['https://ipfs.one.example', 'https://ipfs.two.example'],
|
||||
plebbitRpcClientsOptions: ['ws://127.0.0.1:9138/secret'],
|
||||
pubsubHttpClientsOptions: ['https://pubsub.one.example'],
|
||||
pkcRpcClientsOptions: ['ws://127.0.0.1:9138/secret'],
|
||||
pubsubKuboRpcClientsOptions: ['https://pubsub.one.example'],
|
||||
},
|
||||
});
|
||||
expect(alertSpy).toHaveBeenCalledWith('Options saved, reloading...');
|
||||
@@ -172,8 +172,8 @@ describe('AdvancedSettings', () => {
|
||||
|
||||
it('disables remote-managed textareas and shows the electron data path when RPC is connected', async () => {
|
||||
testState.rpcSettings = {
|
||||
plebbitRpcSettings: {
|
||||
plebbitOptions: {
|
||||
pkcRpcSettings: {
|
||||
pkcOptions: {
|
||||
dataPath: '/tmp/connected-node',
|
||||
},
|
||||
},
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { memo, RefObject, useRef, useState } from 'react';
|
||||
import { setAccount, useAccount, usePlebbitRpcSettings } from '@bitsocialnet/bitsocial-react-hooks';
|
||||
import { setAccount, useAccount, usePkcRpcSettings } from '@bitsocialnet/bitsocial-react-hooks';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import styles from './advanced-settings.module.css';
|
||||
|
||||
@@ -16,10 +16,10 @@ interface SettingsProps {
|
||||
|
||||
const IPFSGatewaysSettings = ({ ipfsGatewayUrlsRef, mediaIpfsGatewayUrlRef }: SettingsProps) => {
|
||||
const account = useAccount();
|
||||
const { plebbitOptions, mediaIpfsGatewayUrl } = account || {};
|
||||
const { ipfsGatewayUrls } = plebbitOptions || {};
|
||||
const plebbitRpc = usePlebbitRpcSettings();
|
||||
const isConnectedToRpc = plebbitRpc?.state === 'connected';
|
||||
const { pkcOptions, mediaIpfsGatewayUrl } = account || {};
|
||||
const { ipfsGatewayUrls } = pkcOptions || {};
|
||||
const pkcRpc = usePkcRpcSettings();
|
||||
const isConnectedToRpc = pkcRpc?.state === 'connected';
|
||||
const ipfsGatewayUrlsDefaultValue = ipfsGatewayUrls?.join('\n');
|
||||
|
||||
return (
|
||||
@@ -53,11 +53,11 @@ const IPFSGatewaysSettings = ({ ipfsGatewayUrlsRef, mediaIpfsGatewayUrlRef }: Se
|
||||
|
||||
const PubsubProvidersSettings = ({ pubsubProvidersRef }: SettingsProps) => {
|
||||
const account = useAccount();
|
||||
const { plebbitOptions } = account || {};
|
||||
const { pubsubHttpClientsOptions } = plebbitOptions || {};
|
||||
const plebbitRpc = usePlebbitRpcSettings();
|
||||
const isConnectedToRpc = plebbitRpc?.state === 'connected';
|
||||
const pubsubProvidersDefaultValue = pubsubHttpClientsOptions?.join('\n');
|
||||
const { pkcOptions } = account || {};
|
||||
const { pubsubKuboRpcClientsOptions } = pkcOptions || {};
|
||||
const pkcRpc = usePkcRpcSettings();
|
||||
const isConnectedToRpc = pkcRpc?.state === 'connected';
|
||||
const pubsubProvidersDefaultValue = pubsubKuboRpcClientsOptions?.join('\n');
|
||||
|
||||
return (
|
||||
<div className={styles.pubsubProvidersSettings}>
|
||||
@@ -69,7 +69,7 @@ const PubsubProvidersSettings = ({ pubsubProvidersRef }: SettingsProps) => {
|
||||
autoCapitalize='off'
|
||||
autoComplete='off'
|
||||
spellCheck='false'
|
||||
rows={pubsubHttpClientsOptions?.length || 1}
|
||||
rows={pubsubKuboRpcClientsOptions?.length || 1}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
@@ -77,10 +77,10 @@ const PubsubProvidersSettings = ({ pubsubProvidersRef }: SettingsProps) => {
|
||||
|
||||
const HttpRoutersSettings = ({ httpRoutersRef }: SettingsProps) => {
|
||||
const account = useAccount();
|
||||
const { plebbitOptions } = account || {};
|
||||
const { httpRoutersOptions } = plebbitOptions || {};
|
||||
const plebbitRpc = usePlebbitRpcSettings();
|
||||
const isConnectedToRpc = plebbitRpc?.state === 'connected';
|
||||
const { pkcOptions } = account || {};
|
||||
const { httpRoutersOptions } = pkcOptions || {};
|
||||
const pkcRpc = usePkcRpcSettings();
|
||||
const isConnectedToRpc = pkcRpc?.state === 'connected';
|
||||
const httpRoutersDefaultValue = httpRoutersOptions?.join('\n');
|
||||
|
||||
return (
|
||||
@@ -101,8 +101,7 @@ const HttpRoutersSettings = ({ httpRoutersRef }: SettingsProps) => {
|
||||
|
||||
const BlockchainProvidersSettings = ({ ethRpcRef, solRpcRef }: SettingsProps) => {
|
||||
const account = useAccount();
|
||||
const { plebbitOptions } = account || {};
|
||||
const { chainProviders } = plebbitOptions || {};
|
||||
const { chainProviders } = account || {};
|
||||
const ethRpcDefaultValue = chainProviders?.['eth']?.urls.join('\n');
|
||||
const solRpcDefaultValue = chainProviders?.['sol']?.urls.join('\n');
|
||||
|
||||
@@ -137,13 +136,13 @@ const BlockchainProvidersSettings = ({ ethRpcRef, solRpcRef }: SettingsProps) =>
|
||||
const P2pRPCSettings = ({ p2pRpcRef }: SettingsProps) => {
|
||||
const [showInfo, setShowInfo] = useState(false);
|
||||
const account = useAccount();
|
||||
const { plebbitOptions } = account || {};
|
||||
const { plebbitRpcClientsOptions } = plebbitOptions || {};
|
||||
const { pkcOptions } = account || {};
|
||||
const { pkcRpcClientsOptions } = pkcOptions || {};
|
||||
|
||||
return (
|
||||
<div className={styles.p2pRPCSettings}>
|
||||
<div>
|
||||
<input type='text' defaultValue={plebbitRpcClientsOptions} ref={p2pRpcRef} autoCorrect='off' autoCapitalize='off' spellCheck='false' />
|
||||
<input type='text' defaultValue={pkcRpcClientsOptions} ref={p2pRpcRef} autoCorrect='off' autoCapitalize='off' spellCheck='false' />
|
||||
<button onClick={() => setShowInfo(!showInfo)}>{showInfo ? 'X' : '?'}</button>
|
||||
</div>
|
||||
{showInfo && (
|
||||
@@ -165,10 +164,10 @@ const P2pRPCSettings = ({ p2pRpcRef }: SettingsProps) => {
|
||||
};
|
||||
|
||||
const P2pDataPathSettings = ({ p2pDataPathRef }: SettingsProps) => {
|
||||
const plebbitRpc = usePlebbitRpcSettings();
|
||||
const { plebbitRpcSettings } = plebbitRpc || {};
|
||||
const isConnectedToRpc = plebbitRpc?.state === 'connected';
|
||||
const path = plebbitRpcSettings?.plebbitOptions?.dataPath || '';
|
||||
const pkcRpc = usePkcRpcSettings();
|
||||
const { pkcRpcSettings } = pkcRpc || {};
|
||||
const isConnectedToRpc = pkcRpc?.state === 'connected';
|
||||
const path = pkcRpcSettings?.pkcOptions?.dataPath || '';
|
||||
|
||||
return (
|
||||
<div className={styles.p2pDataPathSettings}>
|
||||
@@ -184,7 +183,7 @@ const isElectron = window.electronApi?.isElectron === true;
|
||||
const AdvancedSettings = () => {
|
||||
const { t } = useTranslation();
|
||||
const account = useAccount();
|
||||
const { plebbitOptions } = account || {};
|
||||
const { pkcOptions } = account || {};
|
||||
|
||||
const ipfsGatewayUrlsRef = useRef<HTMLTextAreaElement>(null);
|
||||
const mediaIpfsGatewayUrlRef = useRef<HTMLInputElement>(null);
|
||||
@@ -203,7 +202,7 @@ const AdvancedSettings = () => {
|
||||
|
||||
const mediaIpfsGatewayUrl = mediaIpfsGatewayUrlRef.current?.value.trim();
|
||||
|
||||
const pubsubHttpClientsOptions = pubsubProvidersRef.current?.value
|
||||
const pubsubKuboRpcClientsOptions = pubsubProvidersRef.current?.value
|
||||
.split('\n')
|
||||
.map((url) => url.trim())
|
||||
.filter((url) => url !== '');
|
||||
@@ -223,7 +222,7 @@ const AdvancedSettings = () => {
|
||||
.map((url) => url.trim())
|
||||
.filter((url) => url !== '');
|
||||
|
||||
const plebbitRpcClientsOptions = p2pRpcRef.current?.value.trim() ? [p2pRpcRef.current.value.trim()] : undefined;
|
||||
const pkcRpcClientsOptions = p2pRpcRef.current?.value.trim() ? [p2pRpcRef.current.value.trim()] : undefined;
|
||||
const dataPath = p2pDataPathRef.current?.value.trim() || undefined;
|
||||
|
||||
const chainProviders: Record<string, { urls: string[] | undefined; chainId: number }> = {};
|
||||
@@ -238,13 +237,13 @@ const AdvancedSettings = () => {
|
||||
await setAccount({
|
||||
...account,
|
||||
mediaIpfsGatewayUrl,
|
||||
plebbitOptions: {
|
||||
...plebbitOptions,
|
||||
chainProviders,
|
||||
pkcOptions: {
|
||||
...pkcOptions,
|
||||
ipfsGatewayUrls,
|
||||
pubsubHttpClientsOptions,
|
||||
chainProviders,
|
||||
pubsubKuboRpcClientsOptions,
|
||||
httpRoutersOptions,
|
||||
plebbitRpcClientsOptions,
|
||||
pkcRpcClientsOptions,
|
||||
dataPath,
|
||||
},
|
||||
});
|
||||
|
||||
@@ -76,12 +76,13 @@ describe('usePublishPost', () => {
|
||||
expect(latestValue.publishPost).toBe(testState.publishCommentMock);
|
||||
expect(latestValue.publishPostOptions).toMatchObject({
|
||||
author: { displayName: 'Alice' },
|
||||
communityAddress: 'music.eth',
|
||||
content: undefined,
|
||||
link: undefined,
|
||||
spoiler: true,
|
||||
subplebbitAddress: 'music.eth',
|
||||
title: 'Hello world',
|
||||
});
|
||||
expect('subplebbitAddress' in latestValue.publishPostOptions).toBe(false);
|
||||
expect(typeof latestValue.publishPostOptions.onChallengeVerification).toBe('function');
|
||||
expect(typeof latestValue.publishPostOptions.onError).toBe('function');
|
||||
});
|
||||
|
||||
@@ -104,14 +104,15 @@ describe('usePublishReply', () => {
|
||||
expect(typeof latestValue.publishReply).toBe('function');
|
||||
expect(testState.lastPublishOptions).toMatchObject({
|
||||
author: { displayName: 'Bob' },
|
||||
communityAddress: 'music.eth',
|
||||
content: 'Replying to >>12',
|
||||
link: undefined,
|
||||
parentCid: 'parent-cid',
|
||||
postCid: 'parent-cid',
|
||||
quotedCids: ['quoted-cid'],
|
||||
spoiler: true,
|
||||
subplebbitAddress: 'music.eth',
|
||||
});
|
||||
expect('subplebbitAddress' in (testState.lastPublishOptions || {})).toBe(false);
|
||||
});
|
||||
|
||||
it('resolves same-board external quote references before triggering publish', async () => {
|
||||
|
||||
@@ -51,7 +51,8 @@ describe('publish stores', () => {
|
||||
expect(state.displayName).toBe('Poster Alias');
|
||||
expect(state.author).toEqual({ address: '0x123', role: 'mod', displayName: 'Poster Alias' });
|
||||
expect(state.publishCommentOptions.author).toEqual({ address: '0x123', role: 'mod', displayName: 'Poster Alias' });
|
||||
expect(state.publishCommentOptions.subplebbitAddress).toBe('music-posting.eth');
|
||||
expect(state.publishCommentOptions.communityAddress).toBe('music-posting.eth');
|
||||
expect('subplebbitAddress' in state.publishCommentOptions).toBe(false);
|
||||
expect(state.publishCommentOptions.title).toBe('Hello');
|
||||
|
||||
state.publishCommentOptions.onChallengeVerification?.({} as never, comment);
|
||||
@@ -82,8 +83,10 @@ describe('publish stores', () => {
|
||||
const state = usePublishReplyStore.getState();
|
||||
expect(state.displayName['parent-1']).toBe('Reply Alias');
|
||||
expect(state.author['parent-1']).toEqual({ address: '0x123', role: 'mod', displayName: 'Reply Alias' });
|
||||
expect(state.publishCommentOptions['parent-1']?.communityAddress).toBe('music-posting.eth');
|
||||
expect(state.publishCommentOptions['parent-1']?.parentCid).toBe('parent-1');
|
||||
expect(state.publishCommentOptions['parent-1']?.postCid).toBe('parent-1');
|
||||
expect('subplebbitAddress' in (state.publishCommentOptions['parent-1'] || {})).toBe(false);
|
||||
|
||||
state.publishCommentOptions['parent-1']?.onChallengeVerification?.({ token: 'challenge' } as never, comment);
|
||||
expect(testState.alertChallengeVerificationFailedMock).toHaveBeenCalledWith({ token: 'challenge' }, comment);
|
||||
|
||||
@@ -40,7 +40,6 @@ const usePublishPostStore = create<SubmitState>((set) => ({
|
||||
|
||||
const publishCommentOptions: PublishCommentOptions = {
|
||||
communityAddress,
|
||||
subplebbitAddress: communityAddress,
|
||||
title,
|
||||
content,
|
||||
link,
|
||||
|
||||
@@ -35,7 +35,6 @@ const usePublishReplyStore = create<ReplyState>((set) => ({
|
||||
|
||||
const publishCommentOptions: PublishCommentOptions = {
|
||||
communityAddress,
|
||||
subplebbitAddress: communityAddress,
|
||||
parentCid,
|
||||
postCid: comment?.postCid || parentCid,
|
||||
content,
|
||||
|
||||
Reference in New Issue
Block a user