@iservu-inc/adf-cli
Version:
CLI tool for AgentDevFramework - AI-assisted development framework with multi-provider AI support
298 lines (243 loc) • 9 kB
JavaScript
const { filterQuestions, scoreQuestionRelevance } = require('../lib/filters/question-filter');
const { PROJECT_TYPES } = require('../lib/analyzers/project-analyzer');
describe('Question Filter', () => {
const sampleQuestions = [
{
id: 'q1',
text: 'What is the user interface design approach?',
guidance: 'Describe your UI design',
category: 'frontend',
phase: 'design'
},
{
id: 'q2',
text: 'What API endpoints will you need?',
guidance: 'List your REST/GraphQL endpoints',
category: 'api',
phase: 'architecture'
},
{
id: 'q3',
text: 'What command-line arguments will your CLI accept?',
guidance: 'Define CLI interface',
category: 'cli',
phase: 'design'
},
{
id: 'q4',
text: 'What database will you use?',
guidance: 'Choose your database',
category: 'backend',
phase: 'architecture'
}
];
describe('filterQuestions', () => {
test('should skip UI questions for CLI tools', () => {
const projectContext = {
type: PROJECT_TYPES.CLI_TOOL,
frameworks: [],
languages: ['JavaScript/TypeScript'],
confidence: 80
};
const result = filterQuestions(sampleQuestions, projectContext, {
enableSmartFiltering: true,
minRelevanceScore: 50
});
// UI question should be skipped
const uiQuestion = result.questions.find(q => q.id === 'q1');
expect(uiQuestion).toBeUndefined();
// CLI question should be kept
const cliQuestion = result.questions.find(q => q.id === 'q3');
expect(cliQuestion).toBeDefined();
expect(result.summary.skipped).toBeGreaterThan(0);
});
test('should skip frontend questions for API servers', () => {
const projectContext = {
type: PROJECT_TYPES.API_SERVER,
frameworks: ['Express'],
languages: ['JavaScript/TypeScript'],
confidence: 85
};
const result = filterQuestions(sampleQuestions, projectContext, {
enableSmartFiltering: true,
minRelevanceScore: 50
});
// UI question should be skipped
const uiQuestion = result.questions.find(q => q.id === 'q1');
expect(uiQuestion).toBeUndefined();
// API question should be kept
const apiQuestion = result.questions.find(q => q.id === 'q2');
expect(apiQuestion).toBeDefined();
});
test('should keep all questions when smart filtering disabled', () => {
const projectContext = {
type: PROJECT_TYPES.CLI_TOOL,
frameworks: [],
languages: ['JavaScript/TypeScript'],
confidence: 80
};
const result = filterQuestions(sampleQuestions, projectContext, {
enableSmartFiltering: false
});
expect(result.questions.length).toBe(sampleQuestions.length);
expect(result.summary.skipped).toBe(0);
});
test('should estimate time saved correctly', () => {
const projectContext = {
type: PROJECT_TYPES.CLI_TOOL,
frameworks: [],
languages: ['JavaScript/TypeScript'],
confidence: 80
};
const result = filterQuestions(sampleQuestions, projectContext, {
enableSmartFiltering: true,
minRelevanceScore: 50
});
expect(result.summary.timeSaved).toBeGreaterThan(0);
// 2 minutes per skipped question
expect(result.summary.timeSaved).toBe(result.summary.skipped * 2);
});
});
describe('scoreQuestionRelevance', () => {
test('should score UI question low for CLI projects', () => {
const question = {
text: 'What is your responsive design approach?',
guidance: 'Describe mobile/desktop layouts'
};
const projectContext = {
type: PROJECT_TYPES.CLI_TOOL,
frameworks: [],
languages: ['JavaScript/TypeScript']
};
const relevance = scoreQuestionRelevance(question, projectContext);
expect(relevance.score).toBeLessThan(70);
expect(relevance.skipReason).toBeTruthy();
});
test('should score API question high for API servers', () => {
const question = {
text: 'What REST API endpoints will you need?',
guidance: 'Define your API routes'
};
const projectContext = {
type: PROJECT_TYPES.API_SERVER,
frameworks: ['Express'],
languages: ['JavaScript/TypeScript']
};
const relevance = scoreQuestionRelevance(question, projectContext);
expect(relevance.score).toBeGreaterThanOrEqual(50);
});
test('should boost relevance for framework-specific questions', () => {
const question = {
text: 'How will you structure your React components?',
guidance: 'Describe component architecture'
};
const projectContext = {
type: PROJECT_TYPES.WEB_APP,
frameworks: ['React'],
languages: ['JavaScript/TypeScript']
};
const relevance = scoreQuestionRelevance(question, projectContext);
expect(relevance.score).toBeGreaterThan(80);
});
test('should reduce relevance for competing framework questions', () => {
const question = {
text: 'How will you set up Angular modules?',
guidance: 'Configure Angular app'
};
const projectContext = {
type: PROJECT_TYPES.WEB_APP,
frameworks: ['React'],
languages: ['JavaScript/TypeScript']
};
const relevance = scoreQuestionRelevance(question, projectContext);
expect(relevance.score).toBeLessThanOrEqual(70);
});
test('should handle projects with no framework gracefully', () => {
const question = {
text: 'What is your project goal?',
guidance: 'Describe main objective'
};
const projectContext = {
type: PROJECT_TYPES.UNKNOWN,
frameworks: [],
languages: []
};
const relevance = scoreQuestionRelevance(question, projectContext);
expect(relevance.score).toBeGreaterThanOrEqual(0);
expect(relevance.score).toBeLessThanOrEqual(100);
});
test('should provide helpful reasons for kept questions', () => {
const question = {
text: 'What CLI commands will you support?',
guidance: 'Define command structure'
};
const projectContext = {
type: PROJECT_TYPES.CLI_TOOL,
frameworks: [],
languages: ['JavaScript/TypeScript']
};
const relevance = scoreQuestionRelevance(question, projectContext);
expect(relevance.reason).toBeTruthy();
expect(relevance.reason.toLowerCase()).toContain('cli');
});
test('should provide helpful reasons for skipped questions', () => {
const question = {
text: 'What browser compatibility do you need?',
guidance: 'List supported browsers'
};
const projectContext = {
type: PROJECT_TYPES.CLI_TOOL,
frameworks: [],
languages: ['JavaScript/TypeScript']
};
const relevance = scoreQuestionRelevance(question, projectContext);
if (relevance.score < 50) {
expect(relevance.skipReason).toBeTruthy();
}
});
});
describe('Edge cases', () => {
test('should handle empty question list', () => {
const projectContext = {
type: PROJECT_TYPES.WEB_APP,
frameworks: ['React'],
languages: ['JavaScript/TypeScript'],
confidence: 80
};
const result = filterQuestions([], projectContext);
expect(result.questions).toEqual([]);
expect(result.summary.total).toBe(0);
expect(result.summary.skipped).toBe(0);
});
test('should handle unknown project type gracefully', () => {
const projectContext = {
type: PROJECT_TYPES.UNKNOWN,
frameworks: [],
languages: [],
confidence: 20
};
const result = filterQuestions(sampleQuestions, projectContext, {
enableSmartFiltering: true,
minRelevanceScore: 50
});
// Should keep most questions when uncertain
expect(result.questions.length).toBeGreaterThan(0);
});
test('should handle missing category in question', () => {
const questionWithoutCategory = {
id: 'q5',
text: 'General question',
guidance: 'Answer this'
};
const projectContext = {
type: PROJECT_TYPES.WEB_APP,
frameworks: [],
languages: [],
confidence: 80
};
const relevance = scoreQuestionRelevance(questionWithoutCategory, projectContext);
expect(relevance.score).toBeGreaterThanOrEqual(0);
expect(relevance.score).toBeLessThanOrEqual(100);
});
});
});