mirror of
https://github.com/bitsocialnet/5chan.git
synced 2026-08-03 07:41:04 +02:00
perf(home): stop popular threads rerenders after load
This commit is contained in:
@@ -0,0 +1,150 @@
|
||||
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']);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user