test(discussion): expand CommentThread coverage
Adds onCountChange-after-reload (loadOnMount=true), null currentUserId isOwn behavior, replies flattened in display. 3 new tests covering ~10 branches. Refs #496. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -232,4 +232,81 @@ describe('CommentThread', () => {
|
|||||||
const calls = fetchSpy.mock.calls.map((c) => c[0].toString());
|
const calls = fetchSpy.mock.calls.map((c) => c[0].toString());
|
||||||
expect(calls.some((c) => c.endsWith('/api/documents/doc-X/comments'))).toBe(true);
|
expect(calls.some((c) => c.endsWith('/api/documents/doc-X/comments'))).toBe(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('does not call onCountChange when loadOnMount=true (initial render path)', async () => {
|
||||||
|
const onCountChange = vi.fn();
|
||||||
|
// Mock the reload fetch to return one comment so onCountChange fires from reload, not from mount-effect
|
||||||
|
fetchSpy.mockResolvedValueOnce(
|
||||||
|
new Response(
|
||||||
|
JSON.stringify([
|
||||||
|
{
|
||||||
|
id: 'c-1',
|
||||||
|
documentId: 'doc-1',
|
||||||
|
content: 'Loaded',
|
||||||
|
authorId: 'u-1',
|
||||||
|
authorName: 'Anna',
|
||||||
|
createdAt: '2026-01-01T00:00:00Z',
|
||||||
|
updatedAt: null,
|
||||||
|
replies: []
|
||||||
|
}
|
||||||
|
]),
|
||||||
|
{ status: 200, headers: { 'Content-Type': 'application/json' } }
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
render(CommentThread, {
|
||||||
|
props: {
|
||||||
|
documentId: 'doc-1',
|
||||||
|
canComment: false,
|
||||||
|
currentUserId: null,
|
||||||
|
initialComments: [],
|
||||||
|
loadOnMount: true,
|
||||||
|
onCountChange
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
await new Promise((r) => setTimeout(r, 50));
|
||||||
|
expect(onCountChange).toHaveBeenCalledWith(1);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('treats currentUserId=null as never owning a comment', async () => {
|
||||||
|
render(CommentThread, {
|
||||||
|
props: {
|
||||||
|
documentId: 'doc-1',
|
||||||
|
canComment: true,
|
||||||
|
currentUserId: null,
|
||||||
|
initialComments: [baseComment({ id: 'c-1', authorId: 'u-1' })]
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
await new Promise((r) => setTimeout(r, 30));
|
||||||
|
// No edit/delete buttons because none is "own"
|
||||||
|
const editBtns = Array.from(document.querySelectorAll('button')).filter((b) =>
|
||||||
|
/bearbeiten/i.test(b.textContent ?? '')
|
||||||
|
);
|
||||||
|
expect(editBtns.length).toBe(0);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('flat-messages flattens replies', async () => {
|
||||||
|
render(CommentThread, {
|
||||||
|
props: {
|
||||||
|
documentId: 'doc-1',
|
||||||
|
canComment: false,
|
||||||
|
currentUserId: null,
|
||||||
|
initialComments: [
|
||||||
|
{
|
||||||
|
...baseComment({ id: 'c-1', content: 'Top' }),
|
||||||
|
replies: [
|
||||||
|
baseComment({ id: 'r-1', content: 'Reply 1' }),
|
||||||
|
baseComment({ id: 'r-2', content: 'Reply 2' })
|
||||||
|
]
|
||||||
|
} as Comment
|
||||||
|
]
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(document.body.textContent).toContain('Top');
|
||||||
|
expect(document.body.textContent).toContain('Reply 1');
|
||||||
|
expect(document.body.textContent).toContain('Reply 2');
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user