fix(accounts): adapt 5chan to compact account history hooks (#1118)

* chore(cursor): use composer-2 for subagents

* fix(accounts): adapt 5chan to compact account history hooks

* fix(accounts): address 5chan account-history review findings
This commit is contained in:
Tommaso Casaburi
2026-03-20 21:25:57 +08:00
committed by GitHub
parent 4ec74bc85e
commit c2e8e169c2
26 changed files with 499 additions and 136 deletions
+30 -5
View File
@@ -7,15 +7,38 @@ import useFreshReplies from '../use-fresh-replies';
(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>;
type TestComment = {
cid?: string;
content?: string;
index?: number;
number?: number;
subplebbitAddress?: string;
};
const testState = vi.hoisted(() => ({
accountComments: [] as Array<Record<string, unknown>>,
replies: [] as Array<Record<string, unknown>>,
accountComments: [] as TestComment[],
accountCommentsCalls: [] as Array<{ commentIndices?: number[] } | undefined>,
replies: [] as TestComment[],
}));
vi.mock('@bitsocialnet/bitsocial-react-hooks', () => ({
useAccountComments: () => ({
accountComments: testState.accountComments,
}),
useAccountComments: (options?: { commentIndices?: number[] }) => {
testState.accountCommentsCalls.push(options);
if (!options?.commentIndices?.length) {
return {
accountComments: testState.accountComments,
};
}
const normalizedCommentIndices = options.commentIndices.filter((commentIndex) => Number.isInteger(commentIndex) && commentIndex >= 0);
return {
accountComments: normalizedCommentIndices
.map((commentIndex) => testState.accountComments.find((accountComment) => accountComment.index === commentIndex))
.filter(Boolean),
};
},
}));
let container: HTMLDivElement;
@@ -36,6 +59,7 @@ const renderHook = () => {
describe('useFreshReplies', () => {
beforeEach(() => {
testState.accountComments = [];
testState.accountCommentsCalls = [];
testState.replies = [];
container = document.createElement('div');
@@ -78,6 +102,7 @@ describe('useFreshReplies', () => {
expect(latestValue[0]).toBe(testState.accountComments[0] as never);
expect(latestValue[0]?.number).toBe(27);
expect(latestValue[1]).toBe(testState.replies[1] as never);
expect(testState.accountCommentsCalls).toContainEqual({ commentIndices: [3] });
testState.accountComments = [
{
@@ -0,0 +1,102 @@
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 useSafeAccountComment from '../use-safe-account-comment';
(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(() => ({
account: undefined as { id?: string; name?: string } | undefined,
accountCommentResult: { cid: 'account-comment' } as { cid?: string },
calls: [] as Array<{ accountName?: string; commentCid?: string; commentIndex?: number }>,
options: undefined as { accountName?: string; commentCid?: string; commentIndex?: number | string } | undefined,
}));
vi.mock('@bitsocialnet/bitsocial-react-hooks', () => ({
useAccount: (options?: { accountName?: string }) => {
if (!options?.accountName) {
return testState.account;
}
return testState.account?.name === options.accountName ? testState.account : undefined;
},
useAccountComment: (options?: { accountName?: string; commentCid?: string; commentIndex?: number }) => {
testState.calls.push(options || {});
return testState.accountCommentResult;
},
}));
let container: HTMLDivElement;
let latestValue: ReturnType<typeof useSafeAccountComment>;
let root: Root;
const HookHarness = () => {
latestValue = useSafeAccountComment(testState.options);
return null;
};
const renderHook = () => {
act(() => {
root.render(createElement(HookHarness));
});
};
describe('useSafeAccountComment', () => {
beforeEach(() => {
testState.account = undefined;
testState.accountCommentResult = { cid: 'account-comment' };
testState.calls = [];
testState.options = undefined;
container = document.createElement('div');
document.body.appendChild(container);
root = createRoot(container);
});
afterEach(() => {
act(() => root.unmount());
container.remove();
});
it('uses a sentinel lookup when there is no active account and no usable lookup input', () => {
renderHook();
expect(testState.calls).toEqual([{ commentIndex: -1 }]);
expect(latestValue?.cid).toBe('account-comment');
});
it('normalizes numeric comment indices before delegating to useAccountComment', () => {
testState.options = { commentIndex: '7' };
renderHook();
expect(testState.calls).toEqual([{ commentIndex: 7 }]);
});
it('falls back to the sentinel lookup for malformed string indices', () => {
testState.options = { commentIndex: '7abc' };
renderHook();
expect(testState.calls).toEqual([{ commentIndex: -1 }]);
});
it('falls back to the sentinel lookup when cid lookup is requested before an account exists', () => {
testState.options = { commentCid: 'reply-cid' };
renderHook();
expect(testState.calls).toEqual([{ commentIndex: -1 }]);
});
it('passes comment cid lookups through once the active account exists', () => {
testState.account = { id: 'account-1', name: 'Account 1' };
testState.options = { commentCid: 'reply-cid' };
renderHook();
expect(testState.calls).toEqual([{ commentCid: 'reply-cid' }]);
});
});