@youdotcom-oss/mcp 1.3.8 → 1.3.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -40,339 +40,415 @@ describe('registerSearchTool', () => {
40
40
  expect(searchTool?.description).toContain('Web and news search');
41
41
  });
42
42
 
43
- test('performs basic search successfully', async () => {
44
- const result = await client.callTool({
45
- name: 'you-search',
46
- arguments: {
47
- query: 'javascript tutorial',
48
- count: 3,
49
- },
50
- });
51
- const content = result.content as { type: string; text: string }[];
52
- expect(result).toHaveProperty('content');
53
- expect(Array.isArray(content)).toBe(true);
54
- expect(content[0]).toHaveProperty('type', 'text');
55
- expect(content[0]).toHaveProperty('text');
56
-
57
- const text = content[0]?.text;
58
- expect(text).toContain('Search Results for');
59
- expect(text).toContain('javascript tutorial');
60
- const structuredContent = result.structuredContent as SearchStructuredContent;
61
- // Should have structured content with minimal format
62
- expect(result).toHaveProperty('structuredContent');
63
- expect(structuredContent).toHaveProperty('resultCounts');
64
- expect(structuredContent.resultCounts).toHaveProperty('web');
65
- expect(structuredContent.resultCounts).toHaveProperty('news');
66
- expect(structuredContent.resultCounts).toHaveProperty('total');
67
- });
43
+ test(
44
+ 'performs basic search successfully',
45
+ async () => {
46
+ const result = await client.callTool({
47
+ name: 'you-search',
48
+ arguments: {
49
+ query: 'javascript tutorial',
50
+ count: 3,
51
+ },
52
+ });
53
+ const content = result.content as { type: string; text: string }[];
54
+ expect(result).toHaveProperty('content');
55
+ expect(Array.isArray(content)).toBe(true);
56
+ expect(content[0]).toHaveProperty('type', 'text');
57
+ expect(content[0]).toHaveProperty('text');
58
+
59
+ const text = content[0]?.text;
60
+ expect(text).toContain('Search Results for');
61
+ expect(text).toContain('javascript tutorial');
62
+ const structuredContent = result.structuredContent as SearchStructuredContent;
63
+ // Should have structured content with minimal format
64
+ expect(result).toHaveProperty('structuredContent');
65
+ expect(structuredContent).toHaveProperty('resultCounts');
66
+ expect(structuredContent.resultCounts).toHaveProperty('web');
67
+ expect(structuredContent.resultCounts).toHaveProperty('news');
68
+ expect(structuredContent.resultCounts).toHaveProperty('total');
69
+ },
70
+ { retry: 2 },
71
+ );
68
72
 
69
- test('handles search with web results formatting', async () => {
70
- const result = await client.callTool({
71
- name: 'you-search',
72
- arguments: {
73
- query: 'react components',
74
- count: 2,
75
- },
76
- });
77
-
78
- const content = result.content as { type: string; text: string }[];
79
- const text = content[0]?.text;
80
- expect(text).toContain('WEB RESULTS:');
81
- expect(text).toContain('Title:');
82
- // URL should NOT be in text content anymore
83
- expect(text).not.toContain('URL:');
84
- expect(text).toContain('Description:');
85
- expect(text).toContain('Snippets:');
86
-
87
- // Verify structured data has result counts
88
- const structuredContent = result.structuredContent as SearchStructuredContent;
89
- expect(structuredContent.resultCounts.web).toBeGreaterThan(0);
90
- expect(structuredContent.resultCounts.total).toBeGreaterThan(0);
91
-
92
- // URLs should be in structuredContent.results
93
- expect(structuredContent.results).toBeDefined();
94
- expect(structuredContent.results?.web).toBeDefined();
95
- expect(structuredContent.results?.web?.length).toBeGreaterThan(0);
96
- expect(structuredContent.results?.web?.[0]).toHaveProperty('url');
97
- expect(structuredContent.results?.web?.[0]).toHaveProperty('title');
98
- });
73
+ test(
74
+ 'handles search with web results formatting',
75
+ async () => {
76
+ const result = await client.callTool({
77
+ name: 'you-search',
78
+ arguments: {
79
+ query: 'react components',
80
+ count: 2,
81
+ },
82
+ });
99
83
 
100
- test('handles search with news results', async () => {
101
- const result = await client.callTool({
102
- name: 'you-search',
103
- arguments: {
104
- query: 'technology news',
105
- count: 2,
106
- },
107
- });
108
-
109
- const content = result.content as { type: string; text: string }[];
110
- const text = content[0]?.text;
111
-
112
- const structuredContent = result.structuredContent as SearchStructuredContent;
113
- // Check if news results are included
114
- if (structuredContent.resultCounts.news > 0) {
115
- expect(text).toContain('NEWS RESULTS:');
116
- expect(text).toContain('Published:');
117
- expect(structuredContent.resultCounts.news).toBeGreaterThan(0);
118
- }
119
- });
84
+ const content = result.content as { type: string; text: string }[];
85
+ const text = content[0]?.text;
86
+ expect(text).toContain('WEB RESULTS:');
87
+ expect(text).toContain('Title:');
88
+ // URL should NOT be in text content anymore
89
+ expect(text).not.toContain('URL:');
90
+ expect(text).toContain('Description:');
91
+ expect(text).toContain('Snippets:');
92
+
93
+ // Verify structured data has result counts
94
+ const structuredContent = result.structuredContent as SearchStructuredContent;
95
+ expect(structuredContent.resultCounts.web).toBeGreaterThan(0);
96
+ expect(structuredContent.resultCounts.total).toBeGreaterThan(0);
97
+
98
+ // URLs should be in structuredContent.results
99
+ expect(structuredContent.results).toBeDefined();
100
+ expect(structuredContent.results?.web).toBeDefined();
101
+ expect(structuredContent.results?.web?.length).toBeGreaterThan(0);
102
+ expect(structuredContent.results?.web?.[0]).toHaveProperty('url');
103
+ expect(structuredContent.results?.web?.[0]).toHaveProperty('title');
104
+ },
105
+ { retry: 2 },
106
+ );
120
107
 
121
- test('handles mixed web and news results with proper separation', async () => {
122
- const result = await client.callTool({
123
- name: 'you-search',
124
- arguments: {
125
- query: 'artificial intelligence',
126
- count: 3,
127
- },
128
- });
129
-
130
- const content = result.content as { type: string; text: string }[];
131
- const text = content[0]?.text;
132
-
133
- // Should have web results
134
- expect(text).toContain('WEB RESULTS:');
135
-
136
- const structuredContent = result.structuredContent as SearchStructuredContent;
137
- // If both web and news results exist, check for separator
138
- if (structuredContent.resultCounts.news > 0) {
139
- expect(text).toContain('NEWS RESULTS:');
140
- expect(text).toContain('='.repeat(50));
141
- }
142
- });
108
+ test(
109
+ 'handles search with news results',
110
+ async () => {
111
+ const result = await client.callTool({
112
+ name: 'you-search',
113
+ arguments: {
114
+ query: 'technology news',
115
+ count: 2,
116
+ },
117
+ });
143
118
 
144
- test('handles freshness parameter', async () => {
145
- const result = await client.callTool({
146
- name: 'you-search',
147
- arguments: {
148
- query: 'recent news',
149
- freshness: 'week',
150
- },
151
- });
152
-
153
- const content = result.content as { type: string; text: string }[];
154
- expect(content[0]).toHaveProperty('text');
155
- expect(content[0]?.text).toContain('recent news');
156
- });
119
+ const content = result.content as { type: string; text: string }[];
120
+ const text = content[0]?.text;
157
121
 
158
- test('handles country parameter', async () => {
159
- const result = await client.callTool({
160
- name: 'you-search',
161
- arguments: {
162
- query: 'local news',
163
- country: 'US',
164
- },
165
- });
166
-
167
- const content = result.content as { type: string; text: string }[];
168
- expect(content[0]).toHaveProperty('text');
169
- expect(content[0]?.text).toContain('local news');
170
- });
122
+ const structuredContent = result.structuredContent as SearchStructuredContent;
123
+ // Check if news results are included
124
+ if (structuredContent.resultCounts.news > 0) {
125
+ expect(text).toContain('NEWS RESULTS:');
126
+ expect(text).toContain('Published:');
127
+ expect(structuredContent.resultCounts.news).toBeGreaterThan(0);
128
+ }
129
+ },
130
+ { retry: 2 },
131
+ );
171
132
 
172
- test('handles safesearch parameter', async () => {
173
- const result = await client.callTool({
174
- name: 'you-search',
175
- arguments: {
176
- query: 'educational content',
177
- safesearch: 'strict',
178
- },
179
- });
180
-
181
- const content = result.content as { type: string; text: string }[];
182
- expect(content[0]).toHaveProperty('text');
183
- expect(content[0]?.text).toContain('educational content');
184
- });
133
+ test(
134
+ 'handles mixed web and news results with proper separation',
135
+ async () => {
136
+ const result = await client.callTool({
137
+ name: 'you-search',
138
+ arguments: {
139
+ query: 'artificial intelligence',
140
+ count: 3,
141
+ },
142
+ });
185
143
 
186
- test('handles site parameter', async () => {
187
- const result = await client.callTool({
188
- name: 'you-search',
189
- arguments: {
190
- query: 'react components',
191
- site: 'github.com',
192
- },
193
- });
194
-
195
- const content = result.content as { type: string; text: string }[];
196
- expect(content[0]?.text).toContain('react components');
197
- });
144
+ const content = result.content as { type: string; text: string }[];
145
+ const text = content[0]?.text;
198
146
 
199
- test('handles fileType parameter', async () => {
200
- const result = await client.callTool({
201
- name: 'you-search',
202
- arguments: {
203
- query: 'documentation',
204
- fileType: 'pdf',
205
- },
206
- });
207
-
208
- const content = result.content as { type: string; text: string }[];
209
- expect(content[0]?.text).toContain('documentation');
210
- });
147
+ // Should have web results
148
+ expect(text).toContain('WEB RESULTS:');
211
149
 
212
- test('handles language parameter', async () => {
213
- const result = await client.callTool({
214
- name: 'you-search',
215
- arguments: {
216
- query: 'tutorial',
217
- language: 'es',
218
- },
219
- });
220
-
221
- const content = result.content as { type: string; text: string }[];
222
- expect(content[0]?.text).toContain('tutorial');
223
- });
150
+ const structuredContent = result.structuredContent as SearchStructuredContent;
151
+ // If both web and news results exist, check for separator
152
+ if (structuredContent.resultCounts.news > 0) {
153
+ expect(text).toContain('NEWS RESULTS:');
154
+ expect(text).toContain('='.repeat(50));
155
+ }
156
+ },
157
+ { retry: 2 },
158
+ );
224
159
 
225
- test('handles exactTerms parameter', async () => {
226
- const result = await client.callTool({
227
- name: 'you-search',
228
- arguments: {
229
- query: 'programming',
230
- exactTerms: 'javascript|typescript',
231
- },
232
- });
233
-
234
- const content = result.content as { type: string; text: string }[];
235
- expect(content[0]?.text).toContain('programming');
236
- });
160
+ test(
161
+ 'handles freshness parameter',
162
+ async () => {
163
+ const result = await client.callTool({
164
+ name: 'you-search',
165
+ arguments: {
166
+ query: 'recent news',
167
+ freshness: 'week',
168
+ },
169
+ });
237
170
 
238
- test('handles excludeTerms parameter', async () => {
239
- const result = await client.callTool({
240
- name: 'you-search',
241
- arguments: {
242
- query: 'tutorial',
243
- excludeTerms: 'beginner|basic',
244
- },
245
- });
246
-
247
- const content = result.content as { type: string; text: string }[];
248
- expect(content[0]?.text).toContain('tutorial');
249
- });
171
+ const content = result.content as { type: string; text: string }[];
172
+ expect(content[0]).toHaveProperty('text');
173
+ expect(content[0]?.text).toContain('recent news');
174
+ },
175
+ { retry: 2 },
176
+ );
250
177
 
251
- test('handles multi-word phrases with parentheses in exactTerms', async () => {
252
- const result = await client.callTool({
253
- name: 'you-search',
254
- arguments: {
255
- query: 'programming',
256
- exactTerms: '(machine learning)|typescript',
257
- },
258
- });
259
-
260
- const content = result.content as { type: string; text: string }[];
261
- expect(content[0]?.text).toContain('programming');
262
- });
178
+ test(
179
+ 'handles country parameter',
180
+ async () => {
181
+ const result = await client.callTool({
182
+ name: 'you-search',
183
+ arguments: {
184
+ query: 'local news',
185
+ country: 'US',
186
+ },
187
+ });
263
188
 
264
- test('handles multi-word phrases with parentheses in excludeTerms', async () => {
265
- const result = await client.callTool({
266
- name: 'you-search',
267
- arguments: {
268
- query: 'programming',
269
- excludeTerms: '(social media)|ads',
270
- },
271
- });
272
-
273
- const content = result.content as { type: string; text: string }[];
274
- expect(content[0]?.text).toContain('programming');
275
- });
189
+ const content = result.content as { type: string; text: string }[];
190
+ expect(content[0]).toHaveProperty('text');
191
+ expect(content[0]?.text).toContain('local news');
192
+ },
193
+ { retry: 2 },
194
+ );
276
195
 
277
- test('handles complex search with multiple parameters', async () => {
278
- const result = await client.callTool({
279
- name: 'you-search',
280
- arguments: {
281
- query: 'machine learning tutorial',
282
- count: 5,
283
- offset: 1,
284
- freshness: 'month',
285
- country: 'US',
286
- safesearch: 'moderate',
287
- site: 'github.com',
288
- fileType: 'md',
289
- language: 'en',
290
- },
291
- });
292
-
293
- const content = result.content as { type: string; text: string }[];
294
- expect(content[0]).toHaveProperty('text');
295
- // Test should pass even if no results (very specific query might have no results)
296
-
297
- // Verify results are limited by count if there are results
298
- const structuredContent = result.structuredContent as SearchStructuredContent;
299
- if (structuredContent.resultCounts.web > 0) {
300
- expect(structuredContent.resultCounts.web).toBeLessThanOrEqual(5);
301
- }
302
- });
196
+ test(
197
+ 'handles safesearch parameter',
198
+ async () => {
199
+ const result = await client.callTool({
200
+ name: 'you-search',
201
+ arguments: {
202
+ query: 'educational content',
203
+ safesearch: 'strict',
204
+ },
205
+ });
303
206
 
304
- test('handles special characters in query', async () => {
305
- const result = await client.callTool({
306
- name: 'you-search',
307
- arguments: {
308
- query: 'C++ programming "hello world"',
309
- },
310
- });
311
-
312
- const content = result.content as { type: string; text: string }[];
313
- expect(content[0]).toHaveProperty('text');
314
- expect(content[0]?.text).toContain('C++');
315
- });
207
+ const content = result.content as { type: string; text: string }[];
208
+ expect(content[0]).toHaveProperty('text');
209
+ expect(content[0]?.text).toContain('educational content');
210
+ },
211
+ { retry: 2 },
212
+ );
316
213
 
317
- test('handles empty search results gracefully', async () => {
318
- const result = await client.callTool({
319
- name: 'you-search',
320
- arguments: {
321
- query: '_',
322
- },
323
- });
324
-
325
- const content = result.content as { type: string; text: string }[];
326
-
327
- // Should still have content even if no results
328
- expect(content[0]).toHaveProperty('text');
329
-
330
- const text = content[0]?.text;
331
- const structuredContent = result.structuredContent as SearchStructuredContent;
332
- expect(structuredContent.resultCounts.web).toBe(0);
333
- expect(structuredContent.resultCounts.news).toBe(0);
334
- expect(structuredContent.resultCounts.total).toBe(0);
335
- expect(text).toContain('No results found');
336
- });
214
+ test(
215
+ 'handles site parameter',
216
+ async () => {
217
+ const result = await client.callTool({
218
+ name: 'you-search',
219
+ arguments: {
220
+ query: 'react components',
221
+ site: 'github.com',
222
+ },
223
+ });
337
224
 
338
- test('validates structured response format', async () => {
339
- const result = await client.callTool({
340
- name: 'you-search',
341
- arguments: {
342
- query: `what's the latest tech news`,
343
- count: 2,
344
- },
345
- });
346
-
347
- const structuredContent = result.structuredContent as SearchStructuredContent;
348
- // Validate minimal structured content schema
349
- expect(structuredContent).toHaveProperty('resultCounts');
350
-
351
- // Check result counts structure
352
- const resultCounts = structuredContent.resultCounts;
353
- expect(resultCounts).toHaveProperty('web');
354
- expect(resultCounts).toHaveProperty('news');
355
- expect(resultCounts).toHaveProperty('total');
356
- expect(typeof resultCounts.web).toBe('number');
357
- expect(typeof resultCounts.news).toBe('number');
358
- expect(typeof resultCounts.total).toBe('number');
359
- expect(resultCounts.total).toBe(resultCounts.web + resultCounts.news);
360
- });
225
+ const content = result.content as { type: string; text: string }[];
226
+ expect(content[0]?.text).toContain('react components');
227
+ },
228
+ { retry: 2 },
229
+ );
361
230
 
362
- test('returns error when both exactTerms and excludeTerms are provided', async () => {
363
- const result = await client.callTool({
364
- name: 'you-search',
365
- arguments: {
366
- query: 'programming',
367
- exactTerms: 'javascript',
368
- excludeTerms: 'beginner',
369
- },
370
- });
371
-
372
- expect(result.isError).toBe(true);
373
- const content = result.content as { type: string; text: string }[];
374
- expect(content[0]?.text).toContain('Cannot specify both exactTerms and excludeTerms - please use only one');
375
- });
231
+ test(
232
+ 'handles fileType parameter',
233
+ async () => {
234
+ const result = await client.callTool({
235
+ name: 'you-search',
236
+ arguments: {
237
+ query: 'documentation',
238
+ fileType: 'pdf',
239
+ },
240
+ });
241
+
242
+ const content = result.content as { type: string; text: string }[];
243
+ expect(content[0]?.text).toContain('documentation');
244
+ },
245
+ { retry: 2 },
246
+ );
247
+
248
+ test(
249
+ 'handles language parameter',
250
+ async () => {
251
+ const result = await client.callTool({
252
+ name: 'you-search',
253
+ arguments: {
254
+ query: 'tutorial',
255
+ language: 'es',
256
+ },
257
+ });
258
+
259
+ const content = result.content as { type: string; text: string }[];
260
+ expect(content[0]?.text).toContain('tutorial');
261
+ },
262
+ { retry: 2 },
263
+ );
264
+
265
+ test(
266
+ 'handles exactTerms parameter',
267
+ async () => {
268
+ const result = await client.callTool({
269
+ name: 'you-search',
270
+ arguments: {
271
+ query: 'programming',
272
+ exactTerms: 'javascript|typescript',
273
+ },
274
+ });
275
+
276
+ const content = result.content as { type: string; text: string }[];
277
+ expect(content[0]?.text).toContain('programming');
278
+ },
279
+ { retry: 2 },
280
+ );
281
+
282
+ test(
283
+ 'handles excludeTerms parameter',
284
+ async () => {
285
+ const result = await client.callTool({
286
+ name: 'you-search',
287
+ arguments: {
288
+ query: 'tutorial',
289
+ excludeTerms: 'beginner|basic',
290
+ },
291
+ });
292
+
293
+ const content = result.content as { type: string; text: string }[];
294
+ expect(content[0]?.text).toContain('tutorial');
295
+ },
296
+ { retry: 2 },
297
+ );
298
+
299
+ test(
300
+ 'handles multi-word phrases with parentheses in exactTerms',
301
+ async () => {
302
+ const result = await client.callTool({
303
+ name: 'you-search',
304
+ arguments: {
305
+ query: 'programming',
306
+ exactTerms: '(machine learning)|typescript',
307
+ },
308
+ });
309
+
310
+ const content = result.content as { type: string; text: string }[];
311
+ expect(content[0]?.text).toContain('programming');
312
+ },
313
+ { retry: 2 },
314
+ );
315
+
316
+ test(
317
+ 'handles multi-word phrases with parentheses in excludeTerms',
318
+ async () => {
319
+ const result = await client.callTool({
320
+ name: 'you-search',
321
+ arguments: {
322
+ query: 'programming',
323
+ excludeTerms: '(social media)|ads',
324
+ },
325
+ });
326
+
327
+ const content = result.content as { type: string; text: string }[];
328
+ expect(content[0]?.text).toContain('programming');
329
+ },
330
+ { retry: 2 },
331
+ );
332
+
333
+ test(
334
+ 'handles complex search with multiple parameters',
335
+ async () => {
336
+ const result = await client.callTool({
337
+ name: 'you-search',
338
+ arguments: {
339
+ query: 'machine learning tutorial',
340
+ count: 5,
341
+ offset: 1,
342
+ freshness: 'month',
343
+ country: 'US',
344
+ safesearch: 'moderate',
345
+ site: 'github.com',
346
+ fileType: 'md',
347
+ language: 'en',
348
+ },
349
+ });
350
+
351
+ const content = result.content as { type: string; text: string }[];
352
+ expect(content[0]).toHaveProperty('text');
353
+ // Test should pass even if no results (very specific query might have no results)
354
+
355
+ // Verify results are limited by count if there are results
356
+ const structuredContent = result.structuredContent as SearchStructuredContent;
357
+ if (structuredContent.resultCounts.web > 0) {
358
+ expect(structuredContent.resultCounts.web).toBeLessThanOrEqual(5);
359
+ }
360
+ },
361
+ { retry: 2 },
362
+ );
363
+
364
+ test(
365
+ 'handles special characters in query',
366
+ async () => {
367
+ const result = await client.callTool({
368
+ name: 'you-search',
369
+ arguments: {
370
+ query: 'C++ programming "hello world"',
371
+ },
372
+ });
373
+
374
+ const content = result.content as { type: string; text: string }[];
375
+ expect(content[0]).toHaveProperty('text');
376
+ expect(content[0]?.text).toContain('C++');
377
+ },
378
+ { retry: 2 },
379
+ );
380
+
381
+ test(
382
+ 'handles empty search results gracefully',
383
+ async () => {
384
+ const result = await client.callTool({
385
+ name: 'you-search',
386
+ arguments: {
387
+ query: '_',
388
+ },
389
+ });
390
+
391
+ const content = result.content as { type: string; text: string }[];
392
+
393
+ // Should still have content even if no results
394
+ expect(content[0]).toHaveProperty('text');
395
+
396
+ const text = content[0]?.text;
397
+ const structuredContent = result.structuredContent as SearchStructuredContent;
398
+ expect(structuredContent.resultCounts.web).toBe(0);
399
+ expect(structuredContent.resultCounts.news).toBe(0);
400
+ expect(structuredContent.resultCounts.total).toBe(0);
401
+ expect(text).toContain('No results found');
402
+ },
403
+ { retry: 2 },
404
+ );
405
+
406
+ test(
407
+ 'validates structured response format',
408
+ async () => {
409
+ const result = await client.callTool({
410
+ name: 'you-search',
411
+ arguments: {
412
+ query: `what's the latest tech news`,
413
+ count: 2,
414
+ },
415
+ });
416
+
417
+ const structuredContent = result.structuredContent as SearchStructuredContent;
418
+ // Validate minimal structured content schema
419
+ expect(structuredContent).toHaveProperty('resultCounts');
420
+
421
+ // Check result counts structure
422
+ const resultCounts = structuredContent.resultCounts;
423
+ expect(resultCounts).toHaveProperty('web');
424
+ expect(resultCounts).toHaveProperty('news');
425
+ expect(resultCounts).toHaveProperty('total');
426
+ expect(typeof resultCounts.web).toBe('number');
427
+ expect(typeof resultCounts.news).toBe('number');
428
+ expect(typeof resultCounts.total).toBe('number');
429
+ expect(resultCounts.total).toBe(resultCounts.web + resultCounts.news);
430
+ },
431
+ { retry: 2 },
432
+ );
433
+
434
+ test(
435
+ 'returns error when both exactTerms and excludeTerms are provided',
436
+ async () => {
437
+ const result = await client.callTool({
438
+ name: 'you-search',
439
+ arguments: {
440
+ query: 'programming',
441
+ exactTerms: 'javascript',
442
+ excludeTerms: 'beginner',
443
+ },
444
+ });
445
+
446
+ expect(result.isError).toBe(true);
447
+ const content = result.content as { type: string; text: string }[];
448
+ expect(content[0]?.text).toContain('Cannot specify both exactTerms and excludeTerms - please use only one');
449
+ },
450
+ { retry: 2 },
451
+ );
376
452
 
377
453
  test('handles API errors gracefully', async () => {
378
454
  try {
@@ -387,10 +463,6 @@ describe('registerSearchTool', () => {
387
463
  expect(error).toBeDefined();
388
464
  }
389
465
  });
390
-
391
- test.skip('handles network timeout scenarios', async () => {
392
- // TODO: How do we test this?
393
- });
394
466
  });
395
467
 
396
468
  // NOTE: The following tests require a You.com API key with access to the Contents API
@@ -406,91 +478,107 @@ describe('registerContentsTool', () => {
406
478
  expect(contentsTool?.description).toContain('Extract page content');
407
479
  });
408
480
 
409
- test('extracts content from a single URL', async () => {
410
- const result = await client.callTool({
411
- name: 'you-contents',
412
- arguments: {
413
- urls: ['https://documentation.you.com/developer-resources/mcp-server'],
414
- format: 'markdown',
415
- },
416
- });
417
-
418
- expect(result).toHaveProperty('content');
419
- expect(result).toHaveProperty('structuredContent');
420
-
421
- const content = result.content as { type: string; text: string }[];
422
- expect(Array.isArray(content)).toBe(true);
423
- expect(content[0]).toHaveProperty('type', 'text');
424
- expect(content[0]).toHaveProperty('text');
425
-
426
- const text = content[0]?.text;
427
- expect(text).toContain('Successfully extracted content');
428
- expect(text).toContain('https://documentation.you.com/developer-resources/mcp-server');
429
- expect(text).toContain('Format: markdown');
430
-
431
- const structuredContent = result.structuredContent as ContentsStructuredContent;
432
- expect(structuredContent).toHaveProperty('count', 1);
433
- expect(structuredContent).toHaveProperty('format', 'markdown');
434
- expect(structuredContent).toHaveProperty('items');
435
- expect(structuredContent.items).toHaveLength(1);
436
-
437
- const item = structuredContent.items[0];
438
- expect(item).toBeDefined();
439
-
440
- expect(item).toHaveProperty('url', 'https://documentation.you.com/developer-resources/mcp-server');
441
- expect(item).toHaveProperty('content');
442
- expect(item).toHaveProperty('contentLength');
443
- expect(typeof item?.content).toBe('string');
444
- expect(item?.content.length).toBeGreaterThan(0);
445
- });
481
+ test(
482
+ 'extracts content from a single URL',
483
+ async () => {
484
+ const result = await client.callTool({
485
+ name: 'you-contents',
486
+ arguments: {
487
+ urls: ['https://documentation.you.com/developer-resources/mcp-server'],
488
+ format: 'markdown',
489
+ },
490
+ });
446
491
 
447
- test('extracts content from multiple URLs', async () => {
448
- const result = await client.callTool({
449
- name: 'you-contents',
450
- arguments: {
451
- urls: [
452
- 'https://documentation.you.com/developer-resources/mcp-server',
453
- 'https://documentation.you.com/developer-resources/python-sdk',
454
- ],
455
- format: 'markdown',
456
- },
457
- });
458
-
459
- const structuredContent = result.structuredContent as ContentsStructuredContent;
460
- expect(structuredContent.count).toBe(2);
461
- expect(structuredContent.items).toHaveLength(2);
462
-
463
- const content = result.content as { type: string; text: string }[];
464
- const text = content[0]?.text;
465
- expect(text).toContain('Successfully extracted content from 2 URL(s)');
466
- });
492
+ expect(result).toHaveProperty('content');
493
+ expect(result).toHaveProperty('structuredContent');
494
+
495
+ const content = result.content as { type: string; text: string }[];
496
+ expect(Array.isArray(content)).toBe(true);
497
+ expect(content[0]).toHaveProperty('type', 'text');
498
+ expect(content[0]).toHaveProperty('text');
499
+
500
+ const text = content[0]?.text;
501
+ expect(text).toContain('Successfully extracted content');
502
+ expect(text).toContain('https://documentation.you.com/developer-resources/mcp-server');
503
+ expect(text).toContain('Format: markdown');
504
+
505
+ const structuredContent = result.structuredContent as ContentsStructuredContent;
506
+ expect(structuredContent).toHaveProperty('count', 1);
507
+ expect(structuredContent).toHaveProperty('format', 'markdown');
508
+ expect(structuredContent).toHaveProperty('items');
509
+ expect(structuredContent.items).toHaveLength(1);
510
+
511
+ const item = structuredContent.items[0];
512
+ expect(item).toBeDefined();
513
+
514
+ expect(item).toHaveProperty('url', 'https://documentation.you.com/developer-resources/mcp-server');
515
+ expect(item).toHaveProperty('content');
516
+ expect(item).toHaveProperty('contentLength');
517
+ expect(typeof item?.content).toBe('string');
518
+ expect(item?.content.length).toBeGreaterThan(0);
519
+ },
520
+ { retry: 2 },
521
+ );
522
+
523
+ test(
524
+ 'extracts content from multiple URLs',
525
+ async () => {
526
+ const result = await client.callTool({
527
+ name: 'you-contents',
528
+ arguments: {
529
+ urls: [
530
+ 'https://documentation.you.com/developer-resources/mcp-server',
531
+ 'https://documentation.you.com/developer-resources/python-sdk',
532
+ ],
533
+ format: 'markdown',
534
+ },
535
+ });
467
536
 
468
- test('handles html format', async () => {
469
- const result = await client.callTool({
470
- name: 'you-contents',
471
- arguments: {
472
- urls: ['https://documentation.you.com/developer-resources/mcp-server'],
473
- format: 'html',
474
- },
475
- });
476
-
477
- const structuredContent = result.structuredContent as ContentsStructuredContent;
478
- expect(structuredContent.format).toBe('html');
479
-
480
- const content = result.content as { type: string; text: string }[];
481
- const text = content[0]?.text;
482
- expect(text).toContain('Format: html');
483
- });
537
+ const structuredContent = result.structuredContent as ContentsStructuredContent;
538
+ expect(structuredContent.count).toBe(2);
539
+ expect(structuredContent.items).toHaveLength(2);
540
+
541
+ const content = result.content as { type: string; text: string }[];
542
+ const text = content[0]?.text;
543
+ expect(text).toContain('Successfully extracted content from 2 URL(s)');
544
+ },
545
+ { retry: 2 },
546
+ );
547
+
548
+ test(
549
+ 'handles html format',
550
+ async () => {
551
+ const result = await client.callTool({
552
+ name: 'you-contents',
553
+ arguments: {
554
+ urls: ['https://documentation.you.com/developer-resources/mcp-server'],
555
+ format: 'html',
556
+ },
557
+ });
484
558
 
485
- test('defaults to markdown format when not specified', async () => {
486
- const result = await client.callTool({
487
- name: 'you-contents',
488
- arguments: {
489
- urls: ['https://documentation.you.com/developer-resources/mcp-server'],
490
- },
491
- });
559
+ const structuredContent = result.structuredContent as ContentsStructuredContent;
560
+ expect(structuredContent.format).toBe('html');
492
561
 
493
- const structuredContent = result.structuredContent as ContentsStructuredContent;
494
- expect(structuredContent.format).toBe('markdown');
495
- });
562
+ const content = result.content as { type: string; text: string }[];
563
+ const text = content[0]?.text;
564
+ expect(text).toContain('Format: html');
565
+ },
566
+ { retry: 2 },
567
+ );
568
+
569
+ test(
570
+ 'defaults to markdown format when not specified',
571
+ async () => {
572
+ const result = await client.callTool({
573
+ name: 'you-contents',
574
+ arguments: {
575
+ urls: ['https://documentation.you.com/developer-resources/mcp-server'],
576
+ },
577
+ });
578
+
579
+ const structuredContent = result.structuredContent as ContentsStructuredContent;
580
+ expect(structuredContent.format).toBe('markdown');
581
+ },
582
+ { retry: 2 },
583
+ );
496
584
  });