fix(catalog): use alias-aware media link labels (#1056)

* fix(catalog): use alias-aware media link labels

* fix(settings): align advanced settings tests with save label
This commit is contained in:
Tommaso Casaburi
2026-03-11 22:03:15 +08:00
committed by GitHub
parent 7420ff188d
commit 2dd7c0e8d7
5 changed files with 43 additions and 11 deletions
@@ -111,8 +111,16 @@ vi.mock('../../../lib/utils/post-menu-props', () => ({
}));
vi.mock('../../../hooks/use-directories', () => ({
findDirectoryByAddress: (directories: typeof testState.directories, address?: string) => directories.find((entry) => entry.address === address),
normalizeBoardAddress: (address: string) => address,
findDirectoryByAddress: (directories: typeof testState.directories, address?: string) => {
if (!address) {
return undefined;
}
const normalizeBoardAddress = (value: string) => value.replace(/\.(bso|eth)$/, '');
return directories.find((entry) => entry.address === address) ?? directories.find((entry) => normalizeBoardAddress(entry.address) === normalizeBoardAddress(address));
},
normalizeBoardAddress: (address: string) => address.replace(/\.(bso|eth)$/, ''),
useDirectories: () => testState.directories,
}));
@@ -316,6 +324,30 @@ describe('CatalogRow', () => {
expect(document.body.textContent).toContain('ago:200');
});
it('uses alias-aware board features when deciding whether reply links are media', async () => {
testState.directories = [{ address: 'music-posting.bso', features: { requirePostLinkIsMedia: true }, title: '/mu/ - Music' }];
testState.linkCount = 3;
testState.mediaInfoByLink['https://example.com/media.png'] = { type: 'image', url: 'https://example.com/media.png' };
const post: TestComment = {
author: { address: 'author-1', displayName: 'Alice' },
cid: 'post-alias',
content: 'Alias test',
link: 'https://example.com/media.png',
replyCount: 4,
subplebbitAddress: 'music-posting.eth',
title: 'Alias title',
};
await renderWithRouter(createElement(CatalogRow, { row: [post] }), '/mu/catalog');
expect(container.textContent).toContain('R: 4');
expect(container.textContent).toContain('/ I: 3');
expect(container.textContent).not.toContain('/ L: 3');
expect(document.body.querySelector('a[href="/mu/thread/post-alias"]')).toBeTruthy();
expect(container.querySelector('[title=\"(R)eplies / (I)mage Replies\"]')).toBeTruthy();
});
it('renders hidden and text-only threads with canonical board thread links', async () => {
testState.hiddenCids = new Set(['hidden-1']);
testState.showOPComment = false;
+2 -2
View File
@@ -9,7 +9,7 @@ import { shouldShowSnow } from '../../lib/snow';
import { getHasThumbnail } from '../../lib/utils/media-utils';
import { getFormattedTimeAgo } from '../../lib/utils/time-utils';
import { isAllView, isSubscriptionsView } from '../../lib/utils/view-utils';
import { useDirectories } from '../../hooks/use-directories';
import { findDirectoryByAddress, useDirectories } from '../../hooks/use-directories';
import { getBoardPath } from '../../lib/utils/route-utils';
import useCatalogFiltersStore from '../../stores/use-catalog-filters-store';
import useCatalogStyleStore from '../../stores/use-catalog-style-store';
@@ -130,7 +130,7 @@ const CatalogPost = memo(
const isInAllView = isAllView(location.pathname);
const isInSubscriptionsView = isSubscriptionsView(location.pathname, params);
const directories = useDirectories();
const directoryEntry = directories?.find((c) => c.address === subplebbitAddress);
const directoryEntry = findDirectoryByAddress(directories, subplebbitAddress);
const requirePostLinkIsMedia = directoryEntry?.features?.requirePostLinkIsMedia === true;
const boardPath = subplebbitAddress ? getBoardPath(subplebbitAddress, directories) : '';
const postMenuProps = useMemo(() => selectPostMenuProps(post), [post]);
+2 -2
View File
@@ -13,7 +13,7 @@ import { isValidURL } from '../../lib/utils/url-utils';
import { isAllView, isModQueueView, isModView, isPendingPostView, isPostPageView, isSubscriptionsView } from '../../lib/utils/view-utils';
import { formatUserIDForDisplay, truncateWithEllipsisInMiddle } from '../../lib/utils/string-utils';
import useModQueueStore from '../../stores/use-mod-queue-store';
import { useDirectories } from '../../hooks/use-directories';
import { findDirectoryByAddress, useDirectories } from '../../hooks/use-directories';
import { getBoardPath } from '../../lib/utils/route-utils';
import useAuthorAddressClick from '../../hooks/use-author-address-click';
import { useCommentMediaInfo } from '../../hooks/use-comment-media-info';
@@ -615,7 +615,7 @@ const PostMedia = ({
const [showThumbnail, setShowThumbnail] = useState(true);
const mediaDimensions = getMediaDimensions(commentMediaInfo);
const directoryEntry = directories?.find((c) => c.address === subplebbitAddress);
const directoryEntry = findDirectoryByAddress(directories, subplebbitAddress);
const requirePostLinkIsMedia = directoryEntry?.features?.requirePostLinkIsMedia === true;
const boardPath = getBoardPath(subplebbitAddress, directories);
const displayBoardPath =
+2 -2
View File
@@ -13,7 +13,7 @@ import { approvePendingCommentModeration, isPendingApprovalRejected, rejectPendi
import { isAllView, isModQueueView, isModView, isPendingPostView, isPostPageView, isSubscriptionsView } from '../../lib/utils/view-utils';
import { formatUserIDForDisplay } from '../../lib/utils/string-utils';
import useModQueueStore from '../../stores/use-mod-queue-store';
import { useDirectories } from '../../hooks/use-directories';
import { findDirectoryByAddress, useDirectories } from '../../hooks/use-directories';
import { getBoardPath } from '../../lib/utils/route-utils';
import useAuthorAddressClick from '../../hooks/use-author-address-click';
import { useCommentMediaInfo } from '../../hooks/use-comment-media-info';
@@ -585,7 +585,7 @@ const PostMobile = ({
const isInPendingPostView = isPendingPostView(location.pathname, params);
const isInPostView = isPostPageView(location.pathname, params);
const directories = useDirectories();
const directoryEntry = directories?.find((c) => c.address === subplebbitAddress);
const directoryEntry = findDirectoryByAddress(directories, subplebbitAddress);
const requirePostLinkIsMedia = directoryEntry?.features?.requirePostLinkIsMedia === true;
const boardPath = subplebbitAddress ? getBoardPath(subplebbitAddress, directories) : undefined;
const linksCount = useCountLinksInReplies(post);
@@ -150,7 +150,7 @@ describe('AdvancedSettings', () => {
await dispatchInput(textareas[4], ' https://sol.one.example \n');
await dispatchInput(textInputs[1], ' ws://127.0.0.1:9138/secret ');
await dispatchInput(textInputs[2], ' /tmp/next-plebbit ');
await clickButton('save_options');
await clickButton('save_advanced_settings');
expect(testState.setAccountMock).toHaveBeenCalledWith({
mediaIpfsGatewayUrl: 'https://media.new.example',
@@ -206,7 +206,7 @@ describe('AdvancedSettings', () => {
testState.setAccountMock.mockRejectedValueOnce(new Error('boom'));
await renderSettings(false);
await clickButton('save_options');
await clickButton('save_advanced_settings');
expect(alertSpy).toHaveBeenCalledWith('Error saving options: boom');
expect(consoleLogSpy).toHaveBeenCalledWith(expect.objectContaining({ message: 'boom' }));
@@ -216,7 +216,7 @@ describe('AdvancedSettings', () => {
testState.setAccountMock.mockRejectedValueOnce('bad');
await renderSettings(false);
await clickButton('save_options');
await clickButton('save_advanced_settings');
expect(alertSpy).toHaveBeenCalledWith('Error');
});