mirror of
https://github.com/bitsocialnet/5chan.git
synced 2026-08-03 07:41:04 +02:00
test(ci): align strict community mocks
This commit is contained in:
@@ -48,7 +48,10 @@ const testState = vi.hoisted(() => ({
|
||||
vi.mock('@bitsocialnet/bitsocial-react-hooks', () => ({
|
||||
useAccount: () => testState.account,
|
||||
useAccountComment: ({ commentIndex }: { commentIndex?: number }) => (typeof commentIndex === 'number' ? testState.accountComments[commentIndex] : undefined),
|
||||
useCommunity: ({ communityAddress }: { communityAddress?: string }) => (communityAddress ? testState.subplebbits[communityAddress] : undefined),
|
||||
useCommunity: (options?: { communityAddress?: string; community?: { name?: string; publicKey?: string } }) => {
|
||||
const communityAddress = options?.communityAddress ?? options?.community?.name ?? options?.community?.publicKey;
|
||||
return communityAddress ? testState.subplebbits[communityAddress] : undefined;
|
||||
},
|
||||
useAccountCommunities: () => ({
|
||||
accountCommunities: Object.fromEntries(testState.accountSubplebbitAddresses.map((address) => [address, { address }])),
|
||||
}),
|
||||
|
||||
+213
@@ -0,0 +1,213 @@
|
||||
import * as React from 'react';
|
||||
import { createElement } from 'react';
|
||||
import { createRoot, Root } from 'react-dom/client';
|
||||
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
|
||||
import CryptoAddressSetting from '../crypto-address-setting';
|
||||
|
||||
(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>;
|
||||
|
||||
const SIGNER_ADDRESS = '12D3KooWSignerPublicKey';
|
||||
|
||||
const hookMocks = vi.hoisted(() => ({
|
||||
setAccount: vi.fn(),
|
||||
useAccount: vi.fn(),
|
||||
useResolvedAuthorAddress: vi.fn(),
|
||||
}));
|
||||
|
||||
const TestedCryptoAddressSetting = ((CryptoAddressSetting as unknown as { type?: React.ComponentType }).type ??
|
||||
(CryptoAddressSetting as unknown as React.ComponentType)) as React.ComponentType;
|
||||
|
||||
vi.mock('react-i18next', () => ({
|
||||
useTranslation: () => ({
|
||||
t: (key: string) =>
|
||||
(
|
||||
({
|
||||
check: 'check',
|
||||
crypto_address_not_resolved: 'Crypto address is not resolved yet.',
|
||||
crypto_address_not_yours: 'Crypto address is not yours.',
|
||||
crypto_address_verification: 'if the crypto address is resolved p2p',
|
||||
crypto_address_yours: 'Crypto address belongs to this account.',
|
||||
enter_crypto_address: 'Enter crypto address.',
|
||||
loading: 'loading',
|
||||
save: 'save',
|
||||
saved: 'saved',
|
||||
}) as Record<string, string>
|
||||
)[key] ?? key,
|
||||
}),
|
||||
}));
|
||||
|
||||
vi.mock('@bitsocialnet/bitsocial-react-hooks', () => ({
|
||||
setAccount: hookMocks.setAccount,
|
||||
useAccount: hookMocks.useAccount,
|
||||
useResolvedAuthorAddress: hookMocks.useResolvedAuthorAddress,
|
||||
}));
|
||||
|
||||
let root: Root;
|
||||
let container: HTMLDivElement;
|
||||
let alertSpy: ReturnType<typeof vi.spyOn>;
|
||||
let lastResolveOptions: unknown;
|
||||
let resolvedAuthorState: {
|
||||
chainProvider?: { urls?: string[] };
|
||||
error?: unknown;
|
||||
resolvedAddress?: string | null;
|
||||
state?: string;
|
||||
};
|
||||
|
||||
const render = async () => {
|
||||
await act(async () => {
|
||||
root.render(createElement(TestedCryptoAddressSetting));
|
||||
await Promise.resolve();
|
||||
});
|
||||
};
|
||||
|
||||
const rerender = render;
|
||||
|
||||
const getInput = () => {
|
||||
const input = container.querySelector('input[placeholder="myaddress.bso"]') as HTMLInputElement | null;
|
||||
if (!input) {
|
||||
throw new Error('crypto address input not found');
|
||||
}
|
||||
return input;
|
||||
};
|
||||
|
||||
const getButtonByText = (text: string) => {
|
||||
const button = Array.from(container.querySelectorAll('button')).find((candidate) => (candidate.textContent ?? '').trim() === text);
|
||||
if (!button) {
|
||||
throw new Error(`button "${text}" not found`);
|
||||
}
|
||||
return button as HTMLButtonElement;
|
||||
};
|
||||
|
||||
const setInputValue = async (value: string) => {
|
||||
await act(async () => {
|
||||
const input = getInput();
|
||||
const valueSetter = Object.getOwnPropertyDescriptor(HTMLInputElement.prototype, 'value')?.set;
|
||||
if (!valueSetter) {
|
||||
throw new Error('input value setter not found');
|
||||
}
|
||||
valueSetter.call(input, value);
|
||||
input.dispatchEvent(new Event('input', { bubbles: true }));
|
||||
await Promise.resolve();
|
||||
});
|
||||
};
|
||||
|
||||
describe('CryptoAddressSetting', () => {
|
||||
beforeEach(() => {
|
||||
vi.clearAllMocks();
|
||||
vi.useFakeTimers();
|
||||
|
||||
resolvedAuthorState = {
|
||||
chainProvider: undefined,
|
||||
error: undefined,
|
||||
resolvedAddress: undefined,
|
||||
state: 'initializing',
|
||||
};
|
||||
lastResolveOptions = undefined;
|
||||
|
||||
hookMocks.useAccount.mockReturnValue({
|
||||
author: {
|
||||
address: 'legacy-name.eth',
|
||||
shortAddress: 'legacy-name.eth',
|
||||
},
|
||||
signer: {
|
||||
address: SIGNER_ADDRESS,
|
||||
},
|
||||
});
|
||||
hookMocks.setAccount.mockResolvedValue({});
|
||||
hookMocks.useResolvedAuthorAddress.mockImplementation((options: unknown) => {
|
||||
lastResolveOptions = options;
|
||||
return resolvedAuthorState;
|
||||
});
|
||||
|
||||
alertSpy = vi.spyOn(window, 'alert').mockImplementation(() => undefined);
|
||||
container = document.createElement('div');
|
||||
document.body.appendChild(container);
|
||||
root = createRoot(container);
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
act(() => {
|
||||
vi.runOnlyPendingTimers();
|
||||
root.unmount();
|
||||
});
|
||||
container.remove();
|
||||
alertSpy.mockRestore();
|
||||
vi.useRealTimers();
|
||||
});
|
||||
|
||||
it('uses the full author address as the initial field value', async () => {
|
||||
hookMocks.useAccount.mockReturnValue({
|
||||
author: {
|
||||
address: 'resolved-alias.eth',
|
||||
shortAddress: 'different-short-address',
|
||||
},
|
||||
signer: {
|
||||
address: SIGNER_ADDRESS,
|
||||
},
|
||||
});
|
||||
|
||||
await render();
|
||||
|
||||
expect(getInput().value).toBe('resolved-alias.eth');
|
||||
});
|
||||
|
||||
it('updates the displayed status after async resolution completes', async () => {
|
||||
await render();
|
||||
|
||||
await setInputValue('music-posting.bso');
|
||||
|
||||
expect(container.textContent).toContain('if the crypto address is resolved p2p');
|
||||
|
||||
await act(async () => {
|
||||
getButtonByText('check').click();
|
||||
});
|
||||
|
||||
expect(container.textContent).toContain('loading');
|
||||
expect((lastResolveOptions as { author?: { address?: string } } | undefined)?.author?.address).toBe('music-posting.bso');
|
||||
|
||||
resolvedAuthorState = {
|
||||
...resolvedAuthorState,
|
||||
resolvedAddress: null,
|
||||
state: 'succeeded',
|
||||
};
|
||||
|
||||
await rerender();
|
||||
|
||||
expect(container.textContent).toContain('Crypto address is not resolved yet.');
|
||||
});
|
||||
|
||||
it('saves a verified alias when it resolves to the signer address', async () => {
|
||||
await render();
|
||||
|
||||
await setInputValue('resolved-name.bso');
|
||||
|
||||
await act(async () => {
|
||||
getButtonByText('check').click();
|
||||
});
|
||||
|
||||
resolvedAuthorState = {
|
||||
...resolvedAuthorState,
|
||||
resolvedAddress: SIGNER_ADDRESS,
|
||||
state: 'succeeded',
|
||||
};
|
||||
|
||||
await rerender();
|
||||
|
||||
await act(async () => {
|
||||
getButtonByText('save').click();
|
||||
await Promise.resolve();
|
||||
});
|
||||
|
||||
expect(hookMocks.setAccount).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
author: expect.objectContaining({
|
||||
address: 'resolved-name.bso',
|
||||
}),
|
||||
}),
|
||||
);
|
||||
expect(container.textContent).toContain('saved');
|
||||
expect(getInput().value).toBe('resolved-name.bso');
|
||||
expect(alertSpy).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
@@ -12,114 +12,153 @@ const withErrorHandling = async <T,>(fn: () => Promise<T>, onError: (e: unknown)
|
||||
}
|
||||
};
|
||||
|
||||
const CryptoAddressSetting = () => {
|
||||
const { t } = useTranslation();
|
||||
const account = useAccount();
|
||||
const getInitialCryptoAddress = (address?: string) => (address?.includes('.') ? address : '');
|
||||
|
||||
const [cryptoState, setCryptoState] = useState({
|
||||
cryptoAddress: account?.author?.shortAddress.includes('.') ? account.author.shortAddress : '',
|
||||
checkingCryptoAddress: false,
|
||||
showResolvingMessage: true,
|
||||
resolveString: t('crypto_address_verification'),
|
||||
const getDefaultResolutionStatus = (t: (key: string) => string) => ({
|
||||
resolveClass: '',
|
||||
resolveString: t('crypto_address_verification'),
|
||||
});
|
||||
|
||||
const getResolutionStatus = ({
|
||||
checkedAddress,
|
||||
chainProviderUrls,
|
||||
error,
|
||||
resolvedAddress,
|
||||
signerAddress,
|
||||
state,
|
||||
t,
|
||||
}: {
|
||||
chainProviderUrls?: string[];
|
||||
checkedAddress?: string;
|
||||
error?: unknown;
|
||||
resolvedAddress?: string | null;
|
||||
signerAddress?: string;
|
||||
state?: string;
|
||||
t: (key: string) => string;
|
||||
}) => {
|
||||
if (!checkedAddress) {
|
||||
return getDefaultResolutionStatus(t);
|
||||
}
|
||||
|
||||
if (state === 'failed') {
|
||||
return {
|
||||
resolveClass: styles.red,
|
||||
resolveString: error instanceof Error ? `failed to resolve crypto address, error: ${error.message}` : 'cannot resolve crypto address, unknown error',
|
||||
};
|
||||
}
|
||||
|
||||
if (state === 'resolving' || state === 'ready' || state === 'initializing') {
|
||||
return {
|
||||
resolveClass: styles.yellow,
|
||||
resolveString: chainProviderUrls ? `resolving from ${chainProviderUrls.join(', ')}` : t('loading'),
|
||||
};
|
||||
}
|
||||
|
||||
if (resolvedAddress && resolvedAddress === signerAddress) {
|
||||
return {
|
||||
resolveClass: styles.green,
|
||||
resolveString: t('crypto_address_yours'),
|
||||
};
|
||||
}
|
||||
|
||||
if (resolvedAddress && resolvedAddress !== signerAddress) {
|
||||
return {
|
||||
resolveClass: styles.red,
|
||||
resolveString: t('crypto_address_not_yours'),
|
||||
};
|
||||
}
|
||||
|
||||
if (resolvedAddress === null || state === 'succeeded') {
|
||||
return {
|
||||
resolveClass: styles.red,
|
||||
resolveString: t('crypto_address_not_resolved'),
|
||||
};
|
||||
}
|
||||
|
||||
return getDefaultResolutionStatus(t);
|
||||
};
|
||||
|
||||
const showSavedIndicator = (setSavedCryptoAddress: (value: boolean) => void) => {
|
||||
setSavedCryptoAddress(true);
|
||||
setTimeout(() => {
|
||||
setSavedCryptoAddress(false);
|
||||
}, 2000);
|
||||
};
|
||||
|
||||
const CryptoAddressSettingContent = ({ account }: { account: ReturnType<typeof useAccount> }) => {
|
||||
const { t } = useTranslation();
|
||||
const [cryptoAddress, setCryptoAddress] = useState(() => getInitialCryptoAddress(account?.author?.address));
|
||||
const [checkedAddress, setCheckedAddress] = useState<string>();
|
||||
const [savedCryptoAddress, setSavedCryptoAddress] = useState(false);
|
||||
const [showCryptoAddressInfo, setShowCryptoAddressInfo] = useState(false);
|
||||
|
||||
const signerAddress = account?.signer?.address;
|
||||
const authorToResolve = checkedAddress ? { ...account?.author, address: checkedAddress } : undefined;
|
||||
const { resolvedAddress, state, error, chainProvider } = useResolvedAuthorAddress({ author: authorToResolve, cache: false });
|
||||
const resolutionStatus = getResolutionStatus({
|
||||
chainProviderUrls: chainProvider?.urls,
|
||||
checkedAddress,
|
||||
error,
|
||||
resolvedAddress,
|
||||
signerAddress,
|
||||
state,
|
||||
t,
|
||||
});
|
||||
|
||||
const [savedCryptoAddress, setSavedCryptoAddress] = useState(false);
|
||||
const [shouldResolve, setShouldResolve] = useState(false);
|
||||
|
||||
const authorToResolve = shouldResolve ? { ...account?.author, address: cryptoState.cryptoAddress } : undefined;
|
||||
const { resolvedAddress, state, error, chainProvider } = useResolvedAuthorAddress({ author: authorToResolve, cache: false });
|
||||
|
||||
const [inputValue, setInputValue] = useState(account?.author?.shortAddress.includes('.') ? account.author.shortAddress : '');
|
||||
|
||||
const checkCryptoAddress = () => {
|
||||
setShouldResolve(true);
|
||||
const addressToCheck = inputValue || cryptoState.cryptoAddress;
|
||||
const addressToCheck = cryptoAddress.trim();
|
||||
if (!addressToCheck || !addressToCheck.includes('.')) {
|
||||
alert(t('enter_crypto_address'));
|
||||
return;
|
||||
}
|
||||
|
||||
let resolveString = '';
|
||||
let resolveClass = '';
|
||||
|
||||
if (state === 'failed') {
|
||||
resolveString = error instanceof Error ? `failed to resolve crypto address, error: ${error.message}` : 'cannot resolve crypto address, unknown error';
|
||||
resolveClass = styles.red;
|
||||
} else if (state === 'resolving') {
|
||||
resolveString = `resolving from ${chainProvider?.urls}`;
|
||||
resolveClass = styles.yellow;
|
||||
} else if (resolvedAddress && resolvedAddress === account?.signer?.address) {
|
||||
resolveString = t('crypto_address_yours');
|
||||
resolveClass = styles.green;
|
||||
} else if (resolvedAddress && resolvedAddress !== account?.signer?.address) {
|
||||
resolveString = t('crypto_address_not_yours');
|
||||
resolveClass = styles.red;
|
||||
} else {
|
||||
resolveString = t('crypto_address_verification');
|
||||
resolveClass = '';
|
||||
}
|
||||
|
||||
setCryptoState((prevState) => ({
|
||||
...prevState,
|
||||
cryptoAddress: addressToCheck,
|
||||
showResolvingMessage: true,
|
||||
resolveString,
|
||||
resolveClass,
|
||||
}));
|
||||
setCryptoAddress(addressToCheck);
|
||||
setCheckedAddress(addressToCheck);
|
||||
};
|
||||
|
||||
const saveCryptoAddress = async () => {
|
||||
if (!cryptoState.cryptoAddress || !cryptoState.cryptoAddress.includes('.')) {
|
||||
const addressToSave = cryptoAddress.trim();
|
||||
|
||||
if (!addressToSave || !addressToSave.includes('.')) {
|
||||
alert(t('enter_crypto_address'));
|
||||
return;
|
||||
} else if (cryptoState.cryptoAddress === account?.author?.address) {
|
||||
setSavedCryptoAddress(true);
|
||||
setTimeout(() => {
|
||||
setSavedCryptoAddress(false);
|
||||
}, 2000);
|
||||
}
|
||||
|
||||
if (addressToSave === account?.author?.address) {
|
||||
showSavedIndicator(setSavedCryptoAddress);
|
||||
return;
|
||||
} else if (resolvedAddress && resolvedAddress !== account?.signer?.address) {
|
||||
alert(t('crypto_address_not_yours'));
|
||||
return;
|
||||
} else if (cryptoState.cryptoAddress && !resolvedAddress) {
|
||||
}
|
||||
|
||||
if (checkedAddress !== addressToSave || !resolvedAddress) {
|
||||
alert(t('crypto_address_not_resolved'));
|
||||
return;
|
||||
} else if (resolvedAddress && resolvedAddress === account?.signer?.address) {
|
||||
}
|
||||
|
||||
if (resolvedAddress !== signerAddress) {
|
||||
alert(t('crypto_address_not_yours'));
|
||||
return;
|
||||
}
|
||||
|
||||
const result = await withErrorHandling(
|
||||
() => setAccount({ ...account, author: { ...account?.author, address: cryptoState.cryptoAddress } }),
|
||||
(error) => {
|
||||
if (error instanceof Error) {
|
||||
alert(error.message);
|
||||
console.log(error);
|
||||
() => setAccount({ ...account, author: { ...account?.author, address: addressToSave } }),
|
||||
(publishError) => {
|
||||
if (publishError instanceof Error) {
|
||||
alert(publishError.message);
|
||||
console.log(publishError);
|
||||
} else {
|
||||
console.error('An unknown error occurred:', error);
|
||||
console.error('An unknown error occurred:', publishError);
|
||||
}
|
||||
},
|
||||
);
|
||||
if (result !== undefined) {
|
||||
setShouldResolve(false);
|
||||
setSavedCryptoAddress(true);
|
||||
setTimeout(() => setSavedCryptoAddress(false), 2000);
|
||||
setCryptoState((prevState) => ({
|
||||
...prevState,
|
||||
savedCryptoAddress: true,
|
||||
cryptoAddress: '',
|
||||
checkingCryptoAddress: false,
|
||||
}));
|
||||
}
|
||||
setSavedCryptoAddress(true);
|
||||
setCryptoState((prevState) => ({
|
||||
...prevState,
|
||||
checkingCryptoAddress: false,
|
||||
showResolvingMessage: false,
|
||||
resolveString: t('crypto_address_verification'),
|
||||
resolveClass: '',
|
||||
}));
|
||||
}
|
||||
};
|
||||
|
||||
const [showCryptoAddressInfo, setShowCryptoAddressInfo] = useState(false);
|
||||
if (result === undefined) {
|
||||
return;
|
||||
}
|
||||
|
||||
setCheckedAddress(undefined);
|
||||
setCryptoAddress(addressToSave);
|
||||
showSavedIndicator(setSavedCryptoAddress);
|
||||
};
|
||||
|
||||
return (
|
||||
<div className={styles.setting}>
|
||||
@@ -127,10 +166,10 @@ const CryptoAddressSetting = () => {
|
||||
<input
|
||||
type='text'
|
||||
placeholder='myaddress.bso'
|
||||
value={cryptoState.cryptoAddress}
|
||||
value={cryptoAddress}
|
||||
onChange={(e) => {
|
||||
setInputValue(e.target.value);
|
||||
setCryptoState((prevState) => ({ ...prevState, cryptoAddress: e.target.value }));
|
||||
setCheckedAddress(undefined);
|
||||
setCryptoAddress(e.target.value);
|
||||
}}
|
||||
/>
|
||||
<button className={styles.saveButton} onClick={saveCryptoAddress}>
|
||||
@@ -162,10 +201,17 @@ const CryptoAddressSetting = () => {
|
||||
<button className={styles.button} onClick={checkCryptoAddress}>
|
||||
{t('check')}
|
||||
</button>{' '}
|
||||
<span className={cryptoState.resolveClass}>{cryptoState.resolveString}</span>
|
||||
<span className={resolutionStatus.resolveClass}>{resolutionStatus.resolveString}</span>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
const CryptoAddressSetting = () => {
|
||||
const account = useAccount();
|
||||
const accountResetKey = account?.id ?? account?.name ?? account?.signer?.address ?? account?.author?.address ?? 'default-account';
|
||||
|
||||
return <CryptoAddressSettingContent key={accountResetKey} account={account} />;
|
||||
};
|
||||
|
||||
export default memo(CryptoAddressSetting);
|
||||
|
||||
@@ -35,7 +35,9 @@ vi.mock('@bitsocialnet/bitsocial-react-hooks/dist/stores/feeds', () => ({
|
||||
}));
|
||||
|
||||
vi.mock('../use-directories', () => ({
|
||||
useDirectories: () => [],
|
||||
useDirectoryByAddress: () => testState.community,
|
||||
findDirectoryByAddress: () => undefined,
|
||||
}));
|
||||
|
||||
vi.mock('../use-board-feed-page-size', () => ({
|
||||
@@ -95,9 +97,9 @@ describe('usePostPageNumber', () => {
|
||||
|
||||
expect(renderHook({ postCid: 'post-3', subplebbitAddress: 'music.eth' })).toBe(2);
|
||||
expect(testState.preloadOptions).toEqual({
|
||||
communities: [{ name: 'music.eth' }],
|
||||
postsPerPage: 20,
|
||||
sortType: 'active',
|
||||
communityAddresses: ['music.eth'],
|
||||
});
|
||||
});
|
||||
|
||||
@@ -106,9 +108,9 @@ describe('usePostPageNumber', () => {
|
||||
|
||||
expect(renderHook({ postCid: 'post-4', subplebbitAddress: 'music.eth' })).toBe(2);
|
||||
expect(testState.preloadOptions).toEqual({
|
||||
communities: [{ name: 'music.eth' }],
|
||||
postsPerPage: 20,
|
||||
sortType: 'active',
|
||||
communityAddresses: ['music.eth'],
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -58,6 +58,8 @@ vi.mock('@bitsocialnet/bitsocial-react-hooks', () => ({
|
||||
|
||||
vi.mock('../../../hooks/use-directories', () => ({
|
||||
useDirectories: () => testState.directories,
|
||||
findDirectoryByAddress: (directories: Array<{ address: string; title?: string; directoryCode?: string }>, address: string | undefined) =>
|
||||
directories.find((entry) => entry.address === address || entry.directoryCode === address || entry.title === address),
|
||||
}));
|
||||
|
||||
vi.mock('../../../hooks/use-resolved-subplebbit-address', () => ({
|
||||
|
||||
@@ -159,6 +159,8 @@ vi.mock('../../../hooks/use-directories', () => ({
|
||||
useDirectories: () => testState.directories,
|
||||
useDirectoryAddresses: () => testState.directories.map((entry) => entry.address),
|
||||
useDirectoryByAddress: (address: string | undefined) => (address ? testState.directoryByAddress[address] : undefined),
|
||||
findDirectoryByAddress: (directories: Array<{ address: string; title?: string; directoryCode?: string }>, address: string | undefined) =>
|
||||
directories.find((entry) => entry.address === address || entry.directoryCode === address || entry.title === address),
|
||||
}));
|
||||
|
||||
vi.mock('../../../hooks/use-filtered-directory-addresses', () => ({
|
||||
|
||||
@@ -173,6 +173,8 @@ vi.mock('react-virtuoso', () => ({
|
||||
vi.mock('../../../hooks/use-directories', () => ({
|
||||
useDirectories: () => testState.directories,
|
||||
useDirectoryByAddress: (address: string | undefined) => (address ? testState.directoryByAddress[address] : undefined),
|
||||
findDirectoryByAddress: (directories: Array<{ address: string; title?: string; directoryCode?: string }>, address: string | undefined) =>
|
||||
directories.find((entry) => entry.address === address || entry.directoryCode === address || entry.title === address),
|
||||
}));
|
||||
|
||||
vi.mock('../../../hooks/use-board-feed-page-size', () => ({
|
||||
|
||||
@@ -39,6 +39,8 @@ vi.mock('@bitsocialnet/bitsocial-react-hooks', () => ({
|
||||
vi.mock('../../../hooks/use-directories', () => ({
|
||||
useDirectories: () => testState.directories,
|
||||
useDirectoryAddresses: () => testState.directoryAddresses,
|
||||
findDirectoryByAddress: (directories: Array<{ address: string; title?: string; directoryCode?: string }>, address: string | undefined) =>
|
||||
directories.find((entry) => entry.address === address || entry.directoryCode === address || entry.title === address),
|
||||
}));
|
||||
|
||||
vi.mock('../../../hooks/use-communities-stats', () => ({
|
||||
|
||||
@@ -35,7 +35,10 @@ vi.mock('react-router-dom', async () => {
|
||||
});
|
||||
|
||||
vi.mock('@bitsocialnet/bitsocial-react-hooks', () => ({
|
||||
useCommunity: ({ communityAddress }: { communityAddress?: string }) => (communityAddress ? testState.communities[communityAddress] : undefined),
|
||||
useCommunity: (options?: { communityAddress?: string; community?: { name?: string; publicKey?: string } }) => {
|
||||
const communityAddress = options?.communityAddress ?? options?.community?.name ?? options?.community?.publicKey;
|
||||
return communityAddress ? testState.communities[communityAddress] : undefined;
|
||||
},
|
||||
}));
|
||||
|
||||
vi.mock('../../../hooks/use-directories', async () => {
|
||||
|
||||
Reference in New Issue
Block a user