doctool
Version:
AI-powered documentation validation and management system
253 lines (228 loc) • 10.7 kB
JavaScript
import { describe, it, expect, beforeEach, afterEach } from 'vitest';
import * as fs from 'fs';
import * as path from 'path';
import * as os from 'os';
import { analyzeDirectoryForContent, getCodeContent, createContentGenerationPrompt, generateKnowledgeContent, updateKnowledgeFile, needsAIEnhancement, enhanceKnowledgeFiles } from './aiContentGenerator';
describe('AI Content Generator', () => {
let tempDir;
beforeEach(() => {
tempDir = fs.mkdtempSync(path.join(os.tmpdir(), 'ai-content-test-'));
});
afterEach(() => {
if (fs.existsSync(tempDir)) {
fs.rmSync(tempDir, { recursive: true, force: true });
}
});
describe('analyzeDirectoryForContent', () => {
it('should analyze directory contents correctly', () => {
// Create test files
fs.writeFileSync(path.join(tempDir, 'test.ts'), 'console.log("test");');
fs.writeFileSync(path.join(tempDir, 'config.json'), '{}');
fs.writeFileSync(path.join(tempDir, 'readme.md'), '# Test');
fs.mkdirSync(path.join(tempDir, 'subdir'));
const analysis = analyzeDirectoryForContent(tempDir);
expect(analysis.name).toBe(path.basename(tempDir));
expect(analysis.path).toBe(tempDir);
expect(analysis.files).toContain('test.ts');
expect(analysis.files).toContain('config.json');
expect(analysis.files).toContain('readme.md');
expect(analysis.subdirectories).toContain('subdir');
expect(analysis.codeFiles).toContain('test.ts');
expect(analysis.codeFiles).not.toContain('config.json');
});
it('should read existing knowledge file content', () => {
const knowledgeContent = '# Test Knowledge\nThis is test content.';
fs.writeFileSync(path.join(tempDir, 'knowledge.md'), knowledgeContent);
const analysis = analyzeDirectoryForContent(tempDir);
expect(analysis.currentKnowledgeContent).toBe(knowledgeContent);
});
it('should handle missing directory gracefully', () => {
const nonExistentPath = path.join(tempDir, 'nonexistent');
const analysis = analyzeDirectoryForContent(nonExistentPath);
expect(analysis.files).toEqual([]);
expect(analysis.subdirectories).toEqual([]);
expect(analysis.codeFiles).toEqual([]);
});
});
describe('getCodeContent', () => {
it('should read code file contents', () => {
const tsContent = 'export function test() { return "hello"; }';
const jsContent = 'function legacy() { return "world"; }';
fs.writeFileSync(path.join(tempDir, 'test.ts'), tsContent);
fs.writeFileSync(path.join(tempDir, 'legacy.js'), jsContent);
const codeContent = getCodeContent(tempDir, ['test.ts', 'legacy.js']);
expect(codeContent['test.ts']).toBe(tsContent);
expect(codeContent['legacy.js']).toBe(jsContent);
});
it('should handle missing files gracefully', () => {
const codeContent = getCodeContent(tempDir, ['missing.ts', 'also-missing.js']);
expect(Object.keys(codeContent)).toHaveLength(0);
});
});
describe('createContentGenerationPrompt', () => {
it('should create comprehensive prompt', () => {
const analysis = {
name: 'test-dir',
path: tempDir,
files: ['index.ts', 'config.json'],
subdirectories: ['lib'],
codeFiles: ['index.ts'],
currentKnowledgeContent: '# Old Content'
};
const codeContent = {
'index.ts': 'export const version = "1.0.0";'
};
const prompt = createContentGenerationPrompt(analysis, codeContent);
expect(prompt).toContain('**Directory:** test-dir');
expect(prompt).toContain('- index.ts');
expect(prompt).toContain('- config.json');
expect(prompt).toContain('- lib/');
expect(prompt).toContain('```typescript');
expect(prompt).toContain('export const version = "1.0.0";');
expect(prompt).toContain('**Current knowledge file content:**');
expect(prompt).toContain('# Old Content');
});
it('should handle directory with no existing knowledge file', () => {
const analysis = {
name: 'new-dir',
path: tempDir,
files: ['app.ts'],
subdirectories: [],
codeFiles: ['app.ts']
};
const prompt = createContentGenerationPrompt(analysis, {});
expect(prompt).toContain('No existing knowledge file found');
expect(prompt).toContain('create comprehensive content from scratch');
});
});
describe('generateKnowledgeContent', () => {
it('should generate content for a TypeScript directory', async () => {
// Create a test TypeScript file
const tsContent = `
export class TestValidator {
validate(input: string): boolean {
return input.length > 0;
}
}
export function helper() {
return "utility function";
}
`;
fs.writeFileSync(path.join(tempDir, 'validator.ts'), tsContent);
fs.writeFileSync(path.join(tempDir, 'validator.test.ts'), 'it("should work", () => {});');
const content = await generateKnowledgeContent(tempDir);
expect(content).toBeTruthy();
expect(content).toContain(`# ${path.basename(tempDir)}`);
expect(content).toContain('## Overview');
expect(content).toContain('## Contents');
expect(content).toContain('validator.ts');
expect(content).toContain('validator.test.ts');
expect(content).toContain('TestValidator');
});
it('should generate content for utils directory', async () => {
const utilsTempDir = fs.mkdtempSync(path.join(os.tmpdir(), 'utils-'));
try {
fs.writeFileSync(path.join(utilsTempDir, 'helpers.ts'), 'export function format() {}');
const content = await generateKnowledgeContent(utilsTempDir);
expect(content).toContain('utility functions');
expect(content).toContain('helper modules');
}
finally {
fs.rmSync(utilsTempDir, { recursive: true, force: true });
}
});
});
describe('updateKnowledgeFile', () => {
it('should create knowledge file with timestamp', () => {
const content = '# Test Directory\n\nThis is test content.';
const success = updateKnowledgeFile(tempDir, content);
expect(success).toBe(true);
const knowledgeFilePath = path.join(tempDir, 'knowledge.md');
expect(fs.existsSync(knowledgeFilePath)).toBe(true);
const fileContent = fs.readFileSync(knowledgeFilePath, 'utf8');
expect(fileContent).toContain('# Test Directory');
expect(fileContent).toContain('This is test content.');
expect(fileContent).toContain('*Last updated:');
expect(fileContent).toContain('*Content generated with AI assistance*');
});
it('should handle write errors gracefully', () => {
// Try to write to a path that doesn't exist
const invalidPath = path.join(tempDir, 'nonexistent', 'subdir');
const success = updateKnowledgeFile(invalidPath, 'test content');
expect(success).toBe(false);
});
});
describe('needsAIEnhancement', () => {
it('should detect template placeholders', () => {
const templateContent = `
# test
## Overview
This directory contains [brief description of the directory's purpose].
## Contents
### Files
- \`file.ts\` - [description]
`;
expect(needsAIEnhancement(templateContent)).toBe(true);
});
it('should detect generated content marker', () => {
const generatedContent = `
# test
Some content here.
This file was generated automatically and should be updated with relevant information.
`;
expect(needsAIEnhancement(generatedContent)).toBe(true);
});
it('should not flag enhanced content', () => {
const enhancedContent = `
# test
## Overview
This directory contains utility functions for the application.
## Contents
### Files
- \`helpers.ts\` - Utility functions for common operations
## Purpose
This directory serves as a centralized location for reusable code.
`;
expect(needsAIEnhancement(enhancedContent)).toBe(false);
});
});
describe('enhanceKnowledgeFiles', () => {
it('should enhance knowledge files that need improvement', async () => {
// Create a template knowledge file
const templateContent = `# test
## Overview
This directory contains [brief description of the directory's purpose].
## Contents
### Files
- \`app.ts\` - [description]
---
*Created: 2025-06-30*
*This file was generated automatically and should be updated with relevant information.*`;
fs.writeFileSync(path.join(tempDir, 'knowledge.md'), templateContent);
fs.writeFileSync(path.join(tempDir, 'app.ts'), 'export const app = "test";');
await enhanceKnowledgeFiles(tempDir);
const enhancedContent = fs.readFileSync(path.join(tempDir, 'knowledge.md'), 'utf8');
expect(enhancedContent).not.toContain('[brief description of the directory\'s purpose]');
expect(enhancedContent).not.toContain('[description]');
expect(enhancedContent).toContain('*Content generated with AI assistance*');
});
it('should skip already enhanced files', async () => {
// Create an already enhanced knowledge file
const enhancedContent = `# test
## Overview
This directory contains core application logic.
## Contents
### Files
- \`app.ts\` - Main application entry point
---
*Last updated: 2025-06-30*
*Content generated with AI assistance*`;
fs.writeFileSync(path.join(tempDir, 'knowledge.md'), enhancedContent);
await enhanceKnowledgeFiles(tempDir);
// Content should remain the same (file was already enhanced)
const finalContent = fs.readFileSync(path.join(tempDir, 'knowledge.md'), 'utf8');
expect(finalContent).toBe(enhancedContent);
});
});
});
//# sourceMappingURL=aiContentGenerator.test.js.map