mirror of
https://github.com/Ark0N/Codeman.git
synced 2026-09-30 12:39:42 +02:00
185 lines
6.1 KiB
TypeScript
185 lines
6.1 KiB
TypeScript
/**
|
|
* @fileoverview Tests for /api/generate-plan endpoint validation
|
|
*
|
|
* Tests request validation for the plan generation API.
|
|
* Port: 3191
|
|
*/
|
|
|
|
import { describe, it, expect } from 'vitest';
|
|
|
|
describe('Generate Plan API Validation', () => {
|
|
// Validation logic extracted from server.ts for unit testing
|
|
const validateGeneratePlanRequest = (req: {
|
|
taskDescription?: unknown;
|
|
detailLevel?: unknown;
|
|
}): { valid: boolean; error?: string } => {
|
|
const { taskDescription, detailLevel } = req;
|
|
|
|
if (!taskDescription || typeof taskDescription !== 'string') {
|
|
return { valid: false, error: 'Task description is required' };
|
|
}
|
|
|
|
if (taskDescription.length === 0) {
|
|
return { valid: false, error: 'Task description is required' };
|
|
}
|
|
|
|
if (taskDescription.length > 10000) {
|
|
return { valid: false, error: 'Task description too long (max 10000 chars)' };
|
|
}
|
|
|
|
// Detail level validation (optional, defaults to 'standard')
|
|
if (detailLevel !== undefined) {
|
|
const validLevels = ['brief', 'standard', 'detailed'];
|
|
if (!validLevels.includes(detailLevel as string)) {
|
|
return { valid: false, error: 'Invalid detail level. Must be: brief, standard, or detailed' };
|
|
}
|
|
}
|
|
|
|
return { valid: true };
|
|
};
|
|
|
|
describe('taskDescription validation', () => {
|
|
it('should reject missing taskDescription', () => {
|
|
const result = validateGeneratePlanRequest({});
|
|
expect(result.valid).toBe(false);
|
|
expect(result.error).toContain('required');
|
|
});
|
|
|
|
it('should reject null taskDescription', () => {
|
|
const result = validateGeneratePlanRequest({ taskDescription: null });
|
|
expect(result.valid).toBe(false);
|
|
expect(result.error).toContain('required');
|
|
});
|
|
|
|
it('should reject empty string taskDescription', () => {
|
|
const result = validateGeneratePlanRequest({ taskDescription: '' });
|
|
expect(result.valid).toBe(false);
|
|
expect(result.error).toContain('required');
|
|
});
|
|
|
|
it('should reject non-string taskDescription', () => {
|
|
const result = validateGeneratePlanRequest({ taskDescription: 123 });
|
|
expect(result.valid).toBe(false);
|
|
expect(result.error).toContain('required');
|
|
});
|
|
|
|
it('should reject taskDescription over 10000 chars', () => {
|
|
const longDescription = 'a'.repeat(10001);
|
|
const result = validateGeneratePlanRequest({ taskDescription: longDescription });
|
|
expect(result.valid).toBe(false);
|
|
expect(result.error).toContain('too long');
|
|
});
|
|
|
|
it('should accept taskDescription at exactly 10000 chars', () => {
|
|
const maxDescription = 'a'.repeat(10000);
|
|
const result = validateGeneratePlanRequest({ taskDescription: maxDescription });
|
|
expect(result.valid).toBe(true);
|
|
});
|
|
|
|
it('should accept valid taskDescription', () => {
|
|
const result = validateGeneratePlanRequest({
|
|
taskDescription: 'Implement user authentication with JWT tokens',
|
|
});
|
|
expect(result.valid).toBe(true);
|
|
});
|
|
|
|
it('should accept multi-line taskDescription', () => {
|
|
const result = validateGeneratePlanRequest({
|
|
taskDescription: `Fix the Ralph Loop wizard issues:
|
|
1. Two Skip buttons confusing
|
|
2. Modal height overflow
|
|
3. Dead code references`,
|
|
});
|
|
expect(result.valid).toBe(true);
|
|
});
|
|
});
|
|
|
|
describe('detailLevel validation', () => {
|
|
it('should accept brief detail level', () => {
|
|
const result = validateGeneratePlanRequest({
|
|
taskDescription: 'Build a feature',
|
|
detailLevel: 'brief',
|
|
});
|
|
expect(result.valid).toBe(true);
|
|
});
|
|
|
|
it('should accept standard detail level', () => {
|
|
const result = validateGeneratePlanRequest({
|
|
taskDescription: 'Build a feature',
|
|
detailLevel: 'standard',
|
|
});
|
|
expect(result.valid).toBe(true);
|
|
});
|
|
|
|
it('should accept detailed detail level', () => {
|
|
const result = validateGeneratePlanRequest({
|
|
taskDescription: 'Build a feature',
|
|
detailLevel: 'detailed',
|
|
});
|
|
expect(result.valid).toBe(true);
|
|
});
|
|
|
|
it('should accept missing detailLevel (defaults to standard)', () => {
|
|
const result = validateGeneratePlanRequest({
|
|
taskDescription: 'Build a feature',
|
|
});
|
|
expect(result.valid).toBe(true);
|
|
});
|
|
|
|
it('should reject invalid detailLevel', () => {
|
|
const result = validateGeneratePlanRequest({
|
|
taskDescription: 'Build a feature',
|
|
detailLevel: 'verbose',
|
|
});
|
|
expect(result.valid).toBe(false);
|
|
expect(result.error).toContain('Invalid detail level');
|
|
});
|
|
|
|
it('should reject numeric detailLevel', () => {
|
|
const result = validateGeneratePlanRequest({
|
|
taskDescription: 'Build a feature',
|
|
detailLevel: 3,
|
|
});
|
|
expect(result.valid).toBe(false);
|
|
expect(result.error).toContain('Invalid detail level');
|
|
});
|
|
});
|
|
|
|
describe('edge cases', () => {
|
|
it('should handle taskDescription with only whitespace', () => {
|
|
// Whitespace-only is technically a valid non-empty string
|
|
// The API accepts it (server-side trim could be added if needed)
|
|
const result = validateGeneratePlanRequest({ taskDescription: ' ' });
|
|
expect(result.valid).toBe(true);
|
|
});
|
|
|
|
it('should handle taskDescription with unicode characters', () => {
|
|
const result = validateGeneratePlanRequest({
|
|
taskDescription: 'Implement 日本語 support with emoji 🎉',
|
|
});
|
|
expect(result.valid).toBe(true);
|
|
});
|
|
|
|
it('should handle taskDescription with special characters', () => {
|
|
const result = validateGeneratePlanRequest({
|
|
taskDescription: 'Fix bug: user@example.com fails with <script>alert(1)</script>',
|
|
});
|
|
expect(result.valid).toBe(true);
|
|
});
|
|
|
|
it('should handle array as taskDescription', () => {
|
|
const result = validateGeneratePlanRequest({
|
|
taskDescription: ['item1', 'item2'],
|
|
});
|
|
expect(result.valid).toBe(false);
|
|
});
|
|
|
|
it('should handle object as taskDescription', () => {
|
|
const result = validateGeneratePlanRequest({
|
|
taskDescription: { text: 'description' },
|
|
});
|
|
expect(result.valid).toBe(false);
|
|
});
|
|
});
|
|
});
|