import * as React from 'react'; import { createElement } from 'react'; import { createRoot, type Root } from 'react-dom/client'; import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'; import type { Comment } from '@bitsocial/bitsocial-react-hooks'; import useHiddenCatalogThreads from '../use-hidden-catalog-threads'; (globalThis as { IS_REACT_ACT_ENVIRONMENT?: boolean }).IS_REACT_ACT_ENVIRONMENT = true; const act = (React as { act?: (cb: () => void | Promise) => void | Promise }).act as (cb: () => void | Promise) => void | Promise; const SPORTS_PUBLIC_KEY = '12D3KooWGJA6zN3Q63FtSgwNhtfA26Skdzdxz5X7A9PFfE4FBMGE'; const testState = vi.hoisted(() => ({ account: { blockedCids: {} as Record }, commentsByCid: {} as Record, directories: [ { address: 'music-posting.eth', directoryCode: 'mu', title: '/mu/ - Music' }, { address: 'sports-posting.bso', directoryCode: 'sp', publicKey: '12D3KooWGJA6zN3Q63FtSgwNhtfA26Skdzdxz5X7A9PFfE4FBMGE', title: '/sp/ - Sports' }, ], })); vi.mock('@bitsocial/bitsocial-react-hooks', () => ({ useAccount: () => testState.account, useComments: ({ commentCids = [] }: { commentCids?: string[] } = {}) => ({ comments: commentCids.map((cid) => testState.commentsByCid[cid]), state: 'succeeded', }), })); vi.mock('../use-directories', async () => { const actual = await vi.importActual('../use-directories'); return { ...actual, useDirectories: () => testState.directories, }; }); const Result = ({ candidateComments = [], communityAddresses, sortType = 'new', }: { candidateComments?: Comment[]; communityAddresses: string[]; sortType?: 'active' | 'new'; }) => { const { hiddenCatalogThreads, scopeKey } = useHiddenCatalogThreads({ candidateComments, communityAddresses, sortType }); return (
{hiddenCatalogThreads.map((thread) => thread.cid).join(',')} {scopeKey}
); }; let container: HTMLDivElement; let root: Root; describe('useHiddenCatalogThreads', () => { beforeEach(() => { testState.account = { blockedCids: {} }; testState.commentsByCid = {}; container = document.createElement('div'); document.body.appendChild(container); root = createRoot(container); }); afterEach(() => { act(() => root.unmount()); container.remove(); }); it('counts hidden threads for a board reached through a directory alias and public key', async () => { testState.account = { blockedCids: { 'hidden-sp-thread': true, 'hidden-sp-reply': true, 'hidden-mu-thread': true } }; testState.commentsByCid = { 'hidden-mu-thread': { cid: 'hidden-mu-thread', communityAddress: 'music-posting.eth', postCid: 'hidden-mu-thread', timestamp: 100, } as Comment, 'hidden-sp-reply': { cid: 'hidden-sp-reply', communityAddress: SPORTS_PUBLIC_KEY, parentCid: 'hidden-sp-thread', postCid: 'hidden-sp-thread', timestamp: 101, } as Comment, 'hidden-sp-thread': { cid: 'hidden-sp-thread', communityAddress: SPORTS_PUBLIC_KEY, postCid: 'hidden-sp-thread', timestamp: 102, } as Comment, }; await act(async () => { root.render(createElement(Result, { communityAddresses: ['sports-posting.bso'] })); }); expect(container.querySelector('[data-testid="hidden-cids"]')?.textContent).toBe('hidden-sp-thread'); }); it('includes hidden threads from every board in a multiboard scope', async () => { testState.account = { blockedCids: { 'hidden-mu-thread': true, 'hidden-other-thread': true, 'hidden-sp-thread': true } }; testState.commentsByCid = { 'hidden-mu-thread': { cid: 'hidden-mu-thread', communityAddress: 'music-posting.eth', postCid: 'hidden-mu-thread', timestamp: 100, } as Comment, 'hidden-other-thread': { cid: 'hidden-other-thread', communityAddress: 'other-board.eth', postCid: 'hidden-other-thread', timestamp: 101, } as Comment, 'hidden-sp-thread': { cid: 'hidden-sp-thread', communityAddress: SPORTS_PUBLIC_KEY, postCid: 'hidden-sp-thread', timestamp: 102, } as Comment, }; await act(async () => { root.render(createElement(Result, { communityAddresses: ['music-posting.eth', 'sports-posting.bso'] })); }); expect(container.querySelector('[data-testid="hidden-cids"]')?.textContent).toBe('hidden-sp-thread,hidden-mu-thread'); }); it('uses candidate comments from the current feed when the blocked cid lookup has not loaded the comment', async () => { testState.account = { blockedCids: { 'hidden-mu-thread': true } }; testState.commentsByCid = {}; await act(async () => { root.render( createElement(Result, { candidateComments: [ { cid: 'hidden-mu-thread', communityAddress: 'music-posting.eth', postCid: 'hidden-mu-thread', timestamp: 100, } as Comment, ], communityAddresses: ['music-posting.eth'], }), ); }); expect(container.querySelector('[data-testid="hidden-cids"]')?.textContent).toBe('hidden-mu-thread'); }); });