mirror of
https://github.com/Ark0N/Codeman.git
synced 2026-09-30 12:39:42 +02:00
chore: bump version to 0.1402
This commit is contained in:
@@ -0,0 +1,184 @@
|
||||
/**
|
||||
* @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);
|
||||
});
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user