Barazo default frontend
barazo.forum
1import { describe, it, expect } from 'vitest'
2import { render, screen } from '@testing-library/react'
3import { TopicList } from './topic-list'
4import { mockTopics } from '@/mocks/data'
5import type { Topic } from '@/lib/api/types'
6
7const baseTopic: Topic = { ...mockTopics[0]! }
8
9describe('TopicList', () => {
10 it('renders all topics', () => {
11 render(<TopicList topics={mockTopics} />)
12 const articles = screen.getAllByRole('article')
13 expect(articles).toHaveLength(mockTopics.length)
14 })
15
16 it('renders topic titles', () => {
17 render(<TopicList topics={mockTopics} />)
18 for (const topic of mockTopics) {
19 expect(screen.getByRole('link', { name: topic.title })).toBeInTheDocument()
20 }
21 })
22
23 it('renders empty state when no topics', () => {
24 render(<TopicList topics={[]} />)
25 expect(screen.getByText(/no topics yet/i)).toBeInTheDocument()
26 })
27
28 it('renders with heading', () => {
29 render(<TopicList topics={mockTopics} heading="Recent Topics" />)
30 expect(screen.getByRole('heading', { name: 'Recent Topics' })).toBeInTheDocument()
31 })
32
33 it('should render "Pinned" heading when there are pinned topics', () => {
34 const topics: Topic[] = [
35 {
36 ...baseTopic,
37 uri: 'at://did:plc:test/forum.barazo.topic.post/p1',
38 rkey: 'p1',
39 isPinned: true,
40 pinnedScope: 'category',
41 pinnedAt: '2026-03-01T00:00:00Z',
42 },
43 {
44 ...baseTopic,
45 uri: 'at://did:plc:test/forum.barazo.topic.post/r1',
46 rkey: 'r1',
47 isPinned: false,
48 pinnedScope: null,
49 pinnedAt: null,
50 },
51 ]
52 render(<TopicList topics={topics} />)
53 expect(screen.getByText('Pinned')).toBeInTheDocument()
54 expect(screen.getByText('Topics')).toBeInTheDocument()
55 })
56
57 it('should not render section headings when no pinned topics', () => {
58 const topics: Topic[] = [
59 {
60 ...baseTopic,
61 uri: 'at://did:plc:test/forum.barazo.topic.post/r1',
62 rkey: 'r1',
63 isPinned: false,
64 pinnedScope: null,
65 pinnedAt: null,
66 },
67 ]
68 render(<TopicList topics={topics} />)
69 expect(screen.queryByText('Pinned')).not.toBeInTheDocument()
70 expect(screen.queryByText('Topics')).not.toBeInTheDocument()
71 })
72
73 it('should render a separator between pinned and regular topics', () => {
74 const topics: Topic[] = [
75 {
76 ...baseTopic,
77 uri: 'at://did:plc:test/forum.barazo.topic.post/p1',
78 rkey: 'p1',
79 isPinned: true,
80 pinnedScope: 'category',
81 pinnedAt: '2026-03-01T00:00:00Z',
82 },
83 {
84 ...baseTopic,
85 uri: 'at://did:plc:test/forum.barazo.topic.post/r1',
86 rkey: 'r1',
87 isPinned: false,
88 pinnedScope: null,
89 pinnedAt: null,
90 },
91 ]
92 render(<TopicList topics={topics} />)
93 expect(screen.getByRole('separator')).toBeInTheDocument()
94 })
95
96 it('should render only pinned section when all topics are pinned', () => {
97 const topics: Topic[] = [
98 {
99 ...baseTopic,
100 uri: 'at://did:plc:test/forum.barazo.topic.post/p1',
101 rkey: 'p1',
102 isPinned: true,
103 pinnedScope: 'category',
104 pinnedAt: '2026-03-01T00:00:00Z',
105 },
106 {
107 ...baseTopic,
108 uri: 'at://did:plc:test/forum.barazo.topic.post/p2',
109 rkey: 'p2',
110 isPinned: true,
111 pinnedScope: 'forum',
112 pinnedAt: '2026-03-02T00:00:00Z',
113 },
114 ]
115 render(<TopicList topics={topics} />)
116 expect(screen.getByText('Pinned')).toBeInTheDocument()
117 // No regular topics section needed, but separator and "Topics" heading still render for consistency
118 const articles = screen.getAllByRole('article')
119 expect(articles).toHaveLength(2)
120 })
121})