Barazo AppView backend
barazo.forum
1import { describe, it, expect } from 'vitest'
2import {
3 createModNoteSchema,
4 modNoteQuerySchema,
5 createTopicNoticeSchema,
6 // dismissTopicNoticeSchema and topicNoticeQuerySchema tested via route-level integration
7 createWarningSchema,
8 warningQuerySchema,
9 acknowledgeWarningSchema,
10} from '../../../src/validation/mod-annotations.js'
11
12describe('mod annotation validation schemas', () => {
13 describe('createModNoteSchema', () => {
14 it('should accept valid user note', () => {
15 const result = createModNoteSchema.safeParse({
16 subjectDid: 'did:plc:abc123',
17 content: 'User was warned verbally in chat.',
18 })
19 expect(result.success).toBe(true)
20 })
21
22 it('should accept valid post note', () => {
23 const result = createModNoteSchema.safeParse({
24 subjectUri: 'at://did:plc:abc/forum.barazo.topic.post/123',
25 content: 'Borderline post, left up after review.',
26 })
27 expect(result.success).toBe(true)
28 })
29
30 it('should reject note with both subjectDid and subjectUri', () => {
31 const result = createModNoteSchema.safeParse({
32 subjectDid: 'did:plc:abc123',
33 subjectUri: 'at://did:plc:abc/forum.barazo.topic.post/123',
34 content: 'Invalid.',
35 })
36 expect(result.success).toBe(false)
37 })
38
39 it('should reject note with neither subjectDid nor subjectUri', () => {
40 const result = createModNoteSchema.safeParse({
41 content: 'No subject.',
42 })
43 expect(result.success).toBe(false)
44 })
45
46 it('should reject empty content', () => {
47 const result = createModNoteSchema.safeParse({
48 subjectDid: 'did:plc:abc123',
49 content: '',
50 })
51 expect(result.success).toBe(false)
52 })
53
54 it('should reject content over 5000 chars', () => {
55 const result = createModNoteSchema.safeParse({
56 subjectDid: 'did:plc:abc123',
57 content: 'a'.repeat(5001),
58 })
59 expect(result.success).toBe(false)
60 })
61 })
62
63 describe('modNoteQuerySchema', () => {
64 it('should accept valid query with subjectDid', () => {
65 const result = modNoteQuerySchema.safeParse({
66 subjectDid: 'did:plc:abc123',
67 })
68 expect(result.success).toBe(true)
69 })
70
71 it('should accept valid query with subjectUri', () => {
72 const result = modNoteQuerySchema.safeParse({
73 subjectUri: 'at://did:plc:abc/forum.barazo.topic.post/123',
74 })
75 expect(result.success).toBe(true)
76 })
77
78 it('should accept query with cursor and limit', () => {
79 const result = modNoteQuerySchema.safeParse({
80 subjectDid: 'did:plc:abc123',
81 cursor: '10',
82 limit: 50,
83 })
84 expect(result.success).toBe(true)
85 })
86
87 it('should default limit to 25', () => {
88 const result = modNoteQuerySchema.safeParse({
89 subjectDid: 'did:plc:abc123',
90 })
91 expect(result.success).toBe(true)
92 if (result.success) {
93 expect(result.data.limit).toBe(25)
94 }
95 })
96 })
97
98 describe('createTopicNoticeSchema', () => {
99 it('should accept valid notice', () => {
100 const result = createTopicNoticeSchema.safeParse({
101 topicUri: 'at://did:plc:abc/forum.barazo.topic.post/123',
102 noticeType: 'closed',
103 headline: 'This topic has been closed.',
104 })
105 expect(result.success).toBe(true)
106 })
107
108 it('should accept notice with optional body', () => {
109 const result = createTopicNoticeSchema.safeParse({
110 topicUri: 'at://did:plc:abc/forum.barazo.topic.post/123',
111 noticeType: 'custom',
112 headline: 'Please read before posting.',
113 body: 'This topic has specific rules.',
114 })
115 expect(result.success).toBe(true)
116 })
117
118 it('should reject headline over 200 chars', () => {
119 const result = createTopicNoticeSchema.safeParse({
120 topicUri: 'at://did:plc:abc/forum.barazo.topic.post/123',
121 noticeType: 'closed',
122 headline: 'a'.repeat(201),
123 })
124 expect(result.success).toBe(false)
125 })
126
127 it('should reject invalid notice type', () => {
128 const result = createTopicNoticeSchema.safeParse({
129 topicUri: 'at://did:plc:abc/forum.barazo.topic.post/123',
130 noticeType: 'invalid',
131 headline: 'Test.',
132 })
133 expect(result.success).toBe(false)
134 })
135 })
136
137 describe('createWarningSchema', () => {
138 it('should accept valid warning', () => {
139 const result = createWarningSchema.safeParse({
140 targetDid: 'did:plc:user123',
141 warningType: 'rule_violation',
142 message: 'Your post violated community rule #3.',
143 })
144 expect(result.success).toBe(true)
145 })
146
147 it('should accept warning with optional fields', () => {
148 const result = createWarningSchema.safeParse({
149 targetDid: 'did:plc:user123',
150 warningType: 'harassment',
151 message: 'Please review our community guidelines.',
152 modComment: 'This is a first offense.',
153 internalNote: 'User has been argumentative in multiple threads.',
154 })
155 expect(result.success).toBe(true)
156 })
157
158 it('should reject modComment over 300 chars', () => {
159 const result = createWarningSchema.safeParse({
160 targetDid: 'did:plc:user123',
161 warningType: 'other',
162 message: 'Warning.',
163 modComment: 'a'.repeat(301),
164 })
165 expect(result.success).toBe(false)
166 })
167
168 it('should reject empty message', () => {
169 const result = createWarningSchema.safeParse({
170 targetDid: 'did:plc:user123',
171 warningType: 'other',
172 message: '',
173 })
174 expect(result.success).toBe(false)
175 })
176 })
177
178 describe('acknowledgeWarningSchema', () => {
179 it('should accept valid warning id param', () => {
180 const result = acknowledgeWarningSchema.safeParse({ id: '5' })
181 expect(result.success).toBe(true)
182 })
183 })
184
185 describe('warningQuerySchema', () => {
186 it('should accept query with targetDid', () => {
187 const result = warningQuerySchema.safeParse({
188 targetDid: 'did:plc:user123',
189 })
190 expect(result.success).toBe(true)
191 })
192
193 it('should default limit to 25', () => {
194 const result = warningQuerySchema.safeParse({})
195 expect(result.success).toBe(true)
196 if (result.success) {
197 expect(result.data.limit).toBe(25)
198 }
199 })
200 })
201})