useAiChat.test.ts201 lines · main
1import { describe, expect, it } from 'vitest'
2
3import { parseSourcesFromContent } from './useAiChat'
4
5describe('parseSourcesFromContent', () => {
6 it('should parse content without sources section', () => {
7 const content = 'This is a simple response without any sources.'
8 const result = parseSourcesFromContent(content)
9
10 expect(result.cleanedContent).toBe(content)
11 expect(result.sources).toEqual([])
12 })
13
14 it('should parse content with sources section at the end', () => {
15 const content = `Here is the answer to your question.
16
17This provides more information.
18
19### Sources
20- /guides/auth
21- /guides/database
22- /reference/api`
23
24 const result = parseSourcesFromContent(content)
25
26 expect(result.cleanedContent).toBe(`Here is the answer to your question.
27
28This provides more information.`)
29 expect(result.sources).toEqual([
30 { path: '/guides/auth', url: 'https://supabase.com/docs/guides/auth' },
31 { path: '/guides/database', url: 'https://supabase.com/docs/guides/database' },
32 { path: '/reference/api', url: 'https://supabase.com/docs/reference/api' },
33 ])
34 })
35
36 it('should parse content with sources section with extra newlines', () => {
37 const content = `Here is the answer to your question.
38
39This provides more information.
40
41### Sources
42
43
44- /guides/auth
45- /guides/database
46- /reference/api`
47
48 const result = parseSourcesFromContent(content)
49
50 expect(result.cleanedContent).toBe(`Here is the answer to your question.
51
52This provides more information.`)
53 expect(result.sources).toEqual([
54 { path: '/guides/auth', url: 'https://supabase.com/docs/guides/auth' },
55 { path: '/guides/database', url: 'https://supabase.com/docs/guides/database' },
56 { path: '/reference/api', url: 'https://supabase.com/docs/reference/api' },
57 ])
58 })
59
60 it('should handle sources section with extra whitespace', () => {
61 const content = `Content here.
62
63### Sources
64- /guides/auth
65- /guides/database`
66
67 const result = parseSourcesFromContent(content)
68
69 expect(result.cleanedContent).toBe('Content here.')
70 expect(result.sources).toEqual([
71 { path: '/guides/auth', url: 'https://supabase.com/docs/guides/auth' },
72 { path: '/guides/database', url: 'https://supabase.com/docs/guides/database' },
73 ])
74 })
75
76 it('should filter out invalid paths that do not start with slash', () => {
77 const content = `Answer here.
78
79### Sources
80- /guides/auth
81- docs/invalid-path
82- https://external-site.com/page
83- /valid/path`
84
85 const result = parseSourcesFromContent(content)
86
87 expect(result.cleanedContent).toBe('Answer here.')
88 expect(result.sources).toEqual([
89 { path: '/guides/auth', url: 'https://supabase.com/docs/guides/auth' },
90 { path: '/valid/path', url: 'https://supabase.com/docs/valid/path' },
91 ])
92 })
93
94 it('should handle empty sources section', () => {
95 const content = `Answer here.
96
97### Sources
98`
99
100 const result = parseSourcesFromContent(content)
101
102 expect(result.cleanedContent).toBe('Answer here.')
103 expect(result.sources).toEqual([])
104 })
105
106 it('should handle sources section with only whitespace', () => {
107 const content = `Answer here.
108
109### Sources
110
111`
112
113 const result = parseSourcesFromContent(content)
114
115 expect(result.cleanedContent).toBe('Answer here.')
116 expect(result.sources).toEqual([])
117 })
118
119 it('should not match sources section that is not at the very end', () => {
120 const content = `Here is some content.
121
122### Sources
123- /guides/auth
124
125More content continues here after sources.`
126
127 const result = parseSourcesFromContent(content)
128
129 expect(result.cleanedContent).toBe(content)
130 expect(result.sources).toEqual([])
131 })
132
133 it('should match sources section with newline after header', () => {
134 const content = `Answer here.
135
136### Sources`
137
138 const result = parseSourcesFromContent(content)
139
140 expect(result.cleanedContent).toBe('Answer here.')
141 expect(result.sources).toEqual([])
142 })
143
144 it('should handle multiple sources sections (only process the last one at the end)', () => {
145 const content = `Content here.
146
147### Sources
148- /guides/first
149
150More content.
151
152### Sources
153- /guides/auth
154- /guides/database`
155
156 const result = parseSourcesFromContent(content)
157
158 expect(result.cleanedContent).toBe(`Content here.
159
160### Sources
161- /guides/first
162
163More content.`)
164 expect(result.sources).toEqual([
165 { path: '/guides/auth', url: 'https://supabase.com/docs/guides/auth' },
166 { path: '/guides/database', url: 'https://supabase.com/docs/guides/database' },
167 ])
168 })
169
170 it('should handle sources with trailing newlines', () => {
171 const content = `Answer here.
172
173### Sources
174- /guides/auth
175- /guides/database
176
177`
178
179 const result = parseSourcesFromContent(content)
180
181 expect(result.cleanedContent).toBe('Answer here.')
182 expect(result.sources).toEqual([
183 { path: '/guides/auth', url: 'https://supabase.com/docs/guides/auth' },
184 { path: '/guides/database', url: 'https://supabase.com/docs/guides/database' },
185 ])
186 })
187
188 it('should handle content with only a sources section', () => {
189 const content = `### Sources
190- /guides/auth
191- /guides/database`
192
193 const result = parseSourcesFromContent(content)
194
195 expect(result.cleanedContent).toBe('')
196 expect(result.sources).toEqual([
197 { path: '/guides/auth', url: 'https://supabase.com/docs/guides/auth' },
198 { path: '/guides/database', url: 'https://supabase.com/docs/guides/database' },
199 ])
200 })
201})