Files
5chan/src/views/home/popular-threads-box/__tests__/popular-threads-box.test.tsx
T

151 lines
4.8 KiB
TypeScript

import * as React from 'react';
import { createElement } from 'react';
import { createRoot, type Root } from 'react-dom/client';
import { MemoryRouter } from 'react-router-dom';
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
import { useFeedStateString } from '../../../../hooks/use-state-string';
import PopularThreadsBox from '../popular-threads-box';
(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 testState = vi.hoisted(() => ({
communities: [] as unknown[],
feedStateString: 'Downloading boards',
isLoading: false,
requestedCommunityIdentifiers: [] as string[][],
requestedCommunities: [] as unknown[][],
revealedPopularPosts: undefined as
| Array<{
cid: string;
communityAddress: string;
content: string;
link: string;
thumbnailUrl: string;
title: string;
}>
| undefined,
popularPosts: [] as Array<{
cid: string;
communityAddress: string;
content: string;
link: string;
thumbnailUrl: string;
title: string;
}>,
}));
vi.mock('react-i18next', () => ({
useTranslation: () => ({
t: (key: string) => key,
}),
}));
vi.mock('@bitsocialnet/bitsocial-react-hooks', () => ({
useCommunities: ({ communities }: { communities: unknown[] }) => {
testState.requestedCommunities.push(communities);
return { communities: testState.communities };
},
}));
vi.mock('../../../../hooks/use-community-identifiers', () => ({
useCommunityIdentifiers: (addresses?: string[]) => {
testState.requestedCommunityIdentifiers.push(addresses || []);
return addresses || [];
},
}));
vi.mock('../../../../hooks/use-state-string', () => ({
useFeedStateString: vi.fn(() => testState.feedStateString),
}));
vi.mock('../../../../hooks/use-popular-posts', () => ({
getRevealedPopularPosts: vi.fn(() => testState.revealedPopularPosts),
default: vi.fn(() => ({
error: null,
isLoading: testState.isLoading,
popularPosts: testState.popularPosts,
})),
}));
vi.mock('../../../../components/catalog-row', () => ({
CatalogPostMedia: ({ cid }: { cid: string }) => createElement('div', { 'data-testid': 'popular-thread-media' }, cid),
}));
vi.mock('../../box-modal', () => ({
default: () => createElement('button', { 'aria-label': 'filters' }),
}));
const directories = [
{ address: 'music-posting.eth', title: '/mu/ - Music' },
{ address: 'tech-posting.eth', title: '/g/ - Technology' },
];
let container: HTMLDivElement;
let root: Root;
const renderPopularThreadsBox = () => {
act(() => {
root.render(createElement(MemoryRouter, {}, createElement(PopularThreadsBox, { directories, directoryAddresses: directories.map((entry) => entry.address) })));
});
};
describe('PopularThreadsBox', () => {
beforeEach(() => {
vi.clearAllMocks();
testState.communities = directories.map((entry) => ({ address: entry.address }));
testState.feedStateString = 'Downloading boards';
testState.isLoading = false;
testState.requestedCommunityIdentifiers = [];
testState.requestedCommunities = [];
testState.revealedPopularPosts = undefined;
testState.popularPosts = [
{
cid: 'thread-1',
communityAddress: 'music-posting.eth',
content: 'thread content',
link: 'https://cdn.example/thread-1.jpg',
thumbnailUrl: 'https://cdn.example/thread-1-thumb.jpg',
title: 'thread title',
},
];
container = document.createElement('div');
document.body.appendChild(container);
root = createRoot(container);
});
afterEach(() => {
act(() => root.unmount());
container.remove();
});
it('does not subscribe to feed state once popular threads are visible', () => {
renderPopularThreadsBox();
expect(container.textContent).toContain('Music');
expect(container.textContent).toContain('thread title');
expect(vi.mocked(useFeedStateString)).not.toHaveBeenCalled();
});
it('does not subscribe to board communities once the popular posts cache is revealed', () => {
testState.revealedPopularPosts = testState.popularPosts;
renderPopularThreadsBox();
expect(testState.requestedCommunityIdentifiers).toEqual([[]]);
expect(testState.requestedCommunities).toEqual([[]]);
expect(container.textContent).toContain('thread title');
});
it('subscribes to feed state only while popular threads are loading', () => {
testState.isLoading = true;
testState.popularPosts = [];
renderPopularThreadsBox();
expect(container.textContent).toContain('Downloading boards');
expect(vi.mocked(useFeedStateString)).toHaveBeenCalledWith(['music-posting.eth', 'tech-posting.eth']);
});
});