mirror of
https://github.com/bitsocialnet/5chan.git
synced 2026-08-03 07:41:04 +02:00
151 lines
4.8 KiB
TypeScript
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']);
|
|
});
|
|
});
|