import { describe, it, expect, mock } from 'bun:test';
import { ContentAnalyzer } from '@/llm/analyzer.js';
import { LLMClient } from '@/llm/client.js';
import { AnalysisType, ContentType, CodeExampleCategory } from '@/llm/types.js';
// Mock LLM Client
const mockLLMClient = {
analyze: mock(),
isAvailable: mock().mockReturnValue(true),
getProviderName: mock().mockReturnValue('mock-provider'),
};
describe('code example extraction', () => {
describe('content analyzer code examples', () => {
it('should extract code examples from full analysis', async () => {
const mockResponse = JSON.stringify({
summary: 'API documentation with examples',
keyPoints: ['REST API', 'Authentication', 'Code samples'],
contentType: 'api_docs',
relevantLinks: [],
codeExamples: [
{
language: 'javascript',
code: 'const response = await fetch("/api/users");',
description: 'Fetch users from API',
category: 'api_call'
},
{
language: 'python',
code: 'import requests\nresponse = requests.get("/api/users")',
description: 'Python API request example',
category: 'api_call'
}
],
confidence: 0.9
});
mockLLMClient.analyze.mockResolvedValue(mockResponse);
const analyzer = new ContentAnalyzer(mockLLMClient as any);
const result = await analyzer.analyzeContent({
content: 'API documentation with code examples',
url: 'https://example.com/api-docs',
title: 'API Documentation',
links: [],
analysisType: AnalysisType.FULL
});
expect(result).not.toBeNull();
expect(result!.codeExamples).toHaveLength(2);
expect(result!.codeExamples[0].language).toBe('javascript');
expect(result!.codeExamples[0].code).toBe('const response = await fetch("/api/users");');
expect(result!.codeExamples[0].description).toBe('Fetch users from API');
expect(result!.codeExamples[0].category).toBe(CodeExampleCategory.API_CALL);
expect(result!.codeExamples[1].language).toBe('python');
});
it('should perform code examples only analysis', async () => {
const mockResponse = JSON.stringify([
{
language: 'bash',
code: 'curl -X GET https://api.example.com/users',
description: 'cURL command to fetch users',
category: 'api_call'
},
{
language: 'json',
code: '{\n "users": [\n {"id": 1, "name": "John"}\n ]\n}',
description: 'Example API response',
category: 'usage_example'
}
]);
mockLLMClient.analyze.mockResolvedValue(mockResponse);
const analyzer = new ContentAnalyzer(mockLLMClient as any);
const result = await analyzer.analyzeContent({
content: 'Documentation with curl examples and JSON responses',
url: 'https://example.com/api-docs',
title: 'API Documentation',
links: [],
analysisType: AnalysisType.CODE_EXAMPLES_ONLY
});
expect(result).not.toBeNull();
expect(result!.summary).toBe('');
expect(result!.keyPoints).toHaveLength(0);
expect(result!.relevantLinks).toHaveLength(0);
expect(result!.codeExamples).toHaveLength(2);
expect(result!.codeExamples[0].language).toBe('bash');
expect(result!.codeExamples[0].category).toBe(CodeExampleCategory.API_CALL);
expect(result!.codeExamples[1].language).toBe('json');
expect(result!.codeExamples[1].category).toBe(CodeExampleCategory.USAGE_EXAMPLE);
expect(result!.confidence).toBe(0.9);
});
it('should handle empty code examples gracefully', async () => {
const mockResponse = JSON.stringify([]);
mockLLMClient.analyze.mockResolvedValue(mockResponse);
const analyzer = new ContentAnalyzer(mockLLMClient as any);
const result = await analyzer.analyzeContent({
content: 'Documentation without code examples',
url: 'https://example.com/docs',
title: 'Documentation',
links: [],
analysisType: AnalysisType.CODE_EXAMPLES_ONLY
});
expect(result).not.toBeNull();
expect(result!.codeExamples).toHaveLength(0);
});
it('should validate and clean code examples', async () => {
const mockResponse = JSON.stringify([
{
language: 'javascript',
code: 'console.log("hello");',
description: 'Log hello to console',
category: 'snippet'
},
{
// Invalid example - missing required fields
language: '',
code: '',
description: 'Invalid example'
},
{
// Invalid category
language: 'python',
code: 'print("world")',
description: 'Print world',
category: 'invalid_category'
}
]);
mockLLMClient.analyze.mockResolvedValue(mockResponse);
const analyzer = new ContentAnalyzer(mockLLMClient as any);
const result = await analyzer.analyzeContent({
content: 'Mixed valid and invalid code examples',
url: 'https://example.com/docs',
title: 'Documentation',
links: [],
analysisType: AnalysisType.CODE_EXAMPLES_ONLY
});
expect(result).not.toBeNull();
// Should filter out the invalid example (empty code)
expect(result!.codeExamples).toHaveLength(2);
expect(result!.codeExamples[0].code).toBe('console.log("hello");');
expect(result!.codeExamples[0].category).toBe(CodeExampleCategory.SNIPPET);
// Invalid category should default to OTHER
expect(result!.codeExamples[1].category).toBe(CodeExampleCategory.OTHER);
});
it('should handle malformed JSON response for code examples', async () => {
mockLLMClient.analyze.mockResolvedValue('invalid json response');
const analyzer = new ContentAnalyzer(mockLLMClient as any);
const result = await analyzer.analyzeContent({
content: 'Content with code examples',
url: 'https://example.com/docs',
title: 'Documentation',
links: [],
analysisType: AnalysisType.CODE_EXAMPLES_ONLY
});
expect(result).toBeNull();
});
it('should categorize different types of code examples', async () => {
const mockResponse = JSON.stringify([
{
language: 'javascript',
code: 'fetch("/api/users").then(r => r.json())',
description: 'API call example',
category: 'api_call'
},
{
language: 'json',
code: '{"database": {"host": "localhost", "port": 5432}}',
description: 'Database configuration',
category: 'configuration'
},
{
language: 'javascript',
code: 'class UserService {\n constructor() {}\n getUsers() {}\n}',
description: 'Complete UserService implementation',
category: 'implementation'
},
{
language: 'bash',
code: 'npm install express',
description: 'Install Express package',
category: 'usage_example'
}
]);
mockLLMClient.analyze.mockResolvedValue(mockResponse);
const analyzer = new ContentAnalyzer(mockLLMClient as any);
const result = await analyzer.analyzeContent({
content: 'Documentation with various code example types',
url: 'https://example.com/docs',
title: 'Documentation',
links: [],
analysisType: AnalysisType.CODE_EXAMPLES_ONLY
});
expect(result).not.toBeNull();
expect(result!.codeExamples).toHaveLength(4);
expect(result!.codeExamples[0].category).toBe(CodeExampleCategory.API_CALL);
expect(result!.codeExamples[1].category).toBe(CodeExampleCategory.CONFIGURATION);
expect(result!.codeExamples[2].category).toBe(CodeExampleCategory.IMPLEMENTATION);
expect(result!.codeExamples[3].category).toBe(CodeExampleCategory.USAGE_EXAMPLE);
});
it('should preserve code formatting and detect languages', async () => {
const multilineCode = `function createUser(userData) {
return fetch('/api/users', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(userData)
});
}`;
const mockResponse = JSON.stringify([
{
language: 'javascript',
code: multilineCode,
description: 'Complete function for creating users',
category: 'complete_example'
}
]);
mockLLMClient.analyze.mockResolvedValue(mockResponse);
const analyzer = new ContentAnalyzer(mockLLMClient as any);
const result = await analyzer.analyzeContent({
content: 'Function documentation',
url: 'https://example.com/docs',
title: 'Documentation',
links: [],
analysisType: AnalysisType.CODE_EXAMPLES_ONLY
});
expect(result).not.toBeNull();
expect(result!.codeExamples).toHaveLength(1);
expect(result!.codeExamples[0].code).toBe(multilineCode);
expect(result!.codeExamples[0].language).toBe('javascript');
expect(result!.codeExamples[0].category).toBe(CodeExampleCategory.COMPLETE_EXAMPLE);
});
});
});