import { updatePromptGroupSchema, validatePromptGroupUpdate, safeValidatePromptGroupUpdate, } from './schemas'; describe('updatePromptGroupSchema', () => { describe('allowed fields', () => { it('should accept valid name field', () => { const result = updatePromptGroupSchema.safeParse({ name: 'Test Group' }); expect(result.success).toBe(true); if (result.success) { expect(result.data.name).toBe('Test Group'); } }); it('should accept valid oneliner field', () => { const result = updatePromptGroupSchema.safeParse({ oneliner: 'A short description' }); expect(result.success).toBe(true); if (result.success) { expect(result.data.oneliner).toBe('A short description'); } }); it('should accept valid category field', () => { const result = updatePromptGroupSchema.safeParse({ category: 'testing' }); expect(result.success).toBe(true); if (result.success) { expect(result.data.category).toBe('testing'); } }); it('should accept valid projectIds array', () => { const result = updatePromptGroupSchema.safeParse({ projectIds: ['proj1', 'proj2'], }); expect(result.success).toBe(true); if (result.success) { expect(result.data.projectIds).toEqual(['proj1', 'proj2']); } }); it('should accept valid removeProjectIds array', () => { const result = updatePromptGroupSchema.safeParse({ removeProjectIds: ['proj1'], }); expect(result.success).toBe(true); if (result.success) { expect(result.data.removeProjectIds).toEqual(['proj1']); } }); it('should accept valid command field', () => { const result = updatePromptGroupSchema.safeParse({ command: 'my-command-123' }); expect(result.success).toBe(true); if (result.success) { expect(result.data.command).toBe('my-command-123'); } }); it('should accept null command field', () => { const result = updatePromptGroupSchema.safeParse({ command: null }); expect(result.success).toBe(true); if (result.success) { expect(result.data.command).toBeNull(); } }); it('should accept multiple valid fields', () => { const input = { name: 'Updated Name', category: 'new-category', oneliner: 'New description', }; const result = updatePromptGroupSchema.safeParse(input); expect(result.success).toBe(true); if (result.success) { expect(result.data).toEqual(input); } }); it('should accept empty object', () => { const result = updatePromptGroupSchema.safeParse({}); expect(result.success).toBe(true); }); }); describe('security - strips sensitive fields', () => { it('should reject author field', () => { const result = updatePromptGroupSchema.safeParse({ name: 'Test', author: '507f1f77bcf86cd799439011', }); expect(result.success).toBe(false); }); it('should reject authorName field', () => { const result = updatePromptGroupSchema.safeParse({ name: 'Test', authorName: 'Malicious Author', }); expect(result.success).toBe(false); }); it('should reject _id field', () => { const result = updatePromptGroupSchema.safeParse({ name: 'Test', _id: '507f1f77bcf86cd799439011', }); expect(result.success).toBe(false); }); it('should reject productionId field', () => { const result = updatePromptGroupSchema.safeParse({ name: 'Test', productionId: '507f1f77bcf86cd799439011', }); expect(result.success).toBe(false); }); it('should reject createdAt field', () => { const result = updatePromptGroupSchema.safeParse({ name: 'Test', createdAt: new Date().toISOString(), }); expect(result.success).toBe(false); }); it('should reject updatedAt field', () => { const result = updatePromptGroupSchema.safeParse({ name: 'Test', updatedAt: new Date().toISOString(), }); expect(result.success).toBe(false); }); it('should reject __v field', () => { const result = updatePromptGroupSchema.safeParse({ name: 'Test', __v: 999, }); expect(result.success).toBe(false); }); it('should reject multiple sensitive fields in a single request', () => { const result = updatePromptGroupSchema.safeParse({ name: 'Legit Name', author: '507f1f77bcf86cd799439011', authorName: 'Hacker', _id: 'newid123', productionId: 'prodid456', createdAt: '2020-01-01T00:00:00.000Z', __v: 999, }); expect(result.success).toBe(false); }); }); describe('validation rules', () => { it('should reject empty name', () => { const result = updatePromptGroupSchema.safeParse({ name: '' }); expect(result.success).toBe(false); }); it('should reject name exceeding max length', () => { const result = updatePromptGroupSchema.safeParse({ name: 'a'.repeat(256) }); expect(result.success).toBe(false); }); it('should reject oneliner exceeding max length', () => { const result = updatePromptGroupSchema.safeParse({ oneliner: 'a'.repeat(501) }); expect(result.success).toBe(false); }); it('should reject category exceeding max length', () => { const result = updatePromptGroupSchema.safeParse({ category: 'a'.repeat(101) }); expect(result.success).toBe(false); }); it('should reject command with invalid characters (uppercase)', () => { const result = updatePromptGroupSchema.safeParse({ command: 'MyCommand' }); expect(result.success).toBe(false); }); it('should reject command with invalid characters (spaces)', () => { const result = updatePromptGroupSchema.safeParse({ command: 'my command' }); expect(result.success).toBe(false); }); it('should reject command with invalid characters (special)', () => { const result = updatePromptGroupSchema.safeParse({ command: 'my_command!' }); expect(result.success).toBe(false); }); }); }); describe('validatePromptGroupUpdate', () => { it('should return validated data for valid input', () => { const input = { name: 'Test', category: 'testing' }; const result = validatePromptGroupUpdate(input); expect(result).toEqual(input); }); it('should throw ZodError for invalid input', () => { expect(() => validatePromptGroupUpdate({ author: 'malicious-id' })).toThrow(); }); }); describe('safeValidatePromptGroupUpdate', () => { it('should return success true for valid input', () => { const result = safeValidatePromptGroupUpdate({ name: 'Test' }); expect(result.success).toBe(true); }); it('should return success false for invalid input with errors', () => { const result = safeValidatePromptGroupUpdate({ author: 'malicious-id' }); expect(result.success).toBe(false); if (!result.success) { expect(result.error.errors.length).toBeGreaterThan(0); } }); });