mirror of
https://github.com/run-llama/auto_rfp.git
synced 2026-07-22 12:35:56 -04:00
f912ce15de
- Configure Vitest with coverage reporting and path aliases - Add test scripts (test, test:run, test:coverage) to package.json - Install vitest, @vitest/coverage-v8, vite-tsconfig-paths, vitest-mock-extended Test coverage includes: - validators: extract-questions, generate-response, llamaparse, multi-step-response - errors: all API error classes with type guard - services: FileValidator (file type/size validation), DefaultResponseService - middleware: apiHandler and withApiHandler request validation Add mock infrastructure for Prisma, OpenAI, and test fixtures
217 lines
6.9 KiB
TypeScript
217 lines
6.9 KiB
TypeScript
import { describe, it, expect } from 'vitest';
|
|
import {
|
|
ApiError,
|
|
ValidationError,
|
|
AuthorizationError,
|
|
ForbiddenError,
|
|
NotFoundError,
|
|
ExternalServiceError,
|
|
LlamaCloudConnectionError,
|
|
AIServiceError,
|
|
DatabaseError,
|
|
ConfigurationError,
|
|
isApiError,
|
|
} from '@/lib/errors/api-errors';
|
|
|
|
describe('ApiError', () => {
|
|
it('should create error with all properties', () => {
|
|
const error = new ApiError('Test error', 500, 'TEST_ERROR');
|
|
expect(error.message).toBe('Test error');
|
|
expect(error.statusCode).toBe(500);
|
|
expect(error.code).toBe('TEST_ERROR');
|
|
expect(error.name).toBe('ApiError');
|
|
});
|
|
|
|
it('should extend Error', () => {
|
|
const error = new ApiError('Test', 400);
|
|
expect(error).toBeInstanceOf(Error);
|
|
});
|
|
|
|
it('should work without code', () => {
|
|
const error = new ApiError('Test', 400);
|
|
expect(error.code).toBeUndefined();
|
|
});
|
|
});
|
|
|
|
describe('ValidationError', () => {
|
|
it('should have correct status code and code', () => {
|
|
const error = new ValidationError('Invalid input');
|
|
expect(error.statusCode).toBe(400);
|
|
expect(error.code).toBe('VALIDATION_ERROR');
|
|
expect(error.name).toBe('ValidationError');
|
|
});
|
|
|
|
it('should store validation details', () => {
|
|
const details = [{ field: 'email', message: 'Invalid email' }];
|
|
const error = new ValidationError('Validation failed', details);
|
|
expect(error.details).toEqual(details);
|
|
});
|
|
|
|
it('should extend ApiError', () => {
|
|
const error = new ValidationError('Test');
|
|
expect(error).toBeInstanceOf(ApiError);
|
|
});
|
|
});
|
|
|
|
describe('AuthorizationError', () => {
|
|
it('should have correct status code and code', () => {
|
|
const error = new AuthorizationError();
|
|
expect(error.statusCode).toBe(401);
|
|
expect(error.code).toBe('UNAUTHORIZED');
|
|
expect(error.name).toBe('AuthorizationError');
|
|
});
|
|
|
|
it('should use default message', () => {
|
|
const error = new AuthorizationError();
|
|
expect(error.message).toBe('Unauthorized');
|
|
});
|
|
|
|
it('should allow custom message', () => {
|
|
const error = new AuthorizationError('Token expired');
|
|
expect(error.message).toBe('Token expired');
|
|
});
|
|
});
|
|
|
|
describe('ForbiddenError', () => {
|
|
it('should have correct status code and code', () => {
|
|
const error = new ForbiddenError();
|
|
expect(error.statusCode).toBe(403);
|
|
expect(error.code).toBe('FORBIDDEN');
|
|
expect(error.name).toBe('ForbiddenError');
|
|
});
|
|
|
|
it('should use default message', () => {
|
|
const error = new ForbiddenError();
|
|
expect(error.message).toBe('Access denied');
|
|
});
|
|
|
|
it('should allow custom message', () => {
|
|
const error = new ForbiddenError('Admin access required');
|
|
expect(error.message).toBe('Admin access required');
|
|
});
|
|
});
|
|
|
|
describe('NotFoundError', () => {
|
|
it('should have correct status code and code', () => {
|
|
const error = new NotFoundError();
|
|
expect(error.statusCode).toBe(404);
|
|
expect(error.code).toBe('NOT_FOUND');
|
|
expect(error.name).toBe('NotFoundError');
|
|
});
|
|
|
|
it('should use default message', () => {
|
|
const error = new NotFoundError();
|
|
expect(error.message).toBe('Resource not found');
|
|
});
|
|
|
|
it('should allow custom message', () => {
|
|
const error = new NotFoundError('Project not found');
|
|
expect(error.message).toBe('Project not found');
|
|
});
|
|
});
|
|
|
|
describe('ExternalServiceError', () => {
|
|
it('should have correct status code and code', () => {
|
|
const error = new ExternalServiceError('Service unavailable', 'OpenAI');
|
|
expect(error.statusCode).toBe(502);
|
|
expect(error.code).toBe('EXTERNAL_SERVICE_ERROR');
|
|
expect(error.name).toBe('ExternalServiceError');
|
|
});
|
|
|
|
it('should store service name', () => {
|
|
const error = new ExternalServiceError('Error', 'LlamaCloud');
|
|
expect(error.service).toBe('LlamaCloud');
|
|
});
|
|
});
|
|
|
|
describe('LlamaCloudConnectionError', () => {
|
|
it('should have correct status code and code', () => {
|
|
const error = new LlamaCloudConnectionError();
|
|
expect(error.statusCode).toBe(502);
|
|
expect(error.code).toBe('EXTERNAL_SERVICE_ERROR');
|
|
expect(error.name).toBe('LlamaCloudConnectionError');
|
|
});
|
|
|
|
it('should use default message', () => {
|
|
const error = new LlamaCloudConnectionError();
|
|
expect(error.message).toBe('LlamaCloud connection failed');
|
|
});
|
|
|
|
it('should allow custom message', () => {
|
|
const error = new LlamaCloudConnectionError('API key invalid');
|
|
expect(error.message).toBe('API key invalid');
|
|
});
|
|
|
|
it('should have LlamaCloud as service', () => {
|
|
const error = new LlamaCloudConnectionError();
|
|
expect(error.service).toBe('LlamaCloud');
|
|
});
|
|
|
|
it('should extend ExternalServiceError', () => {
|
|
const error = new LlamaCloudConnectionError();
|
|
expect(error).toBeInstanceOf(ExternalServiceError);
|
|
});
|
|
});
|
|
|
|
describe('AIServiceError', () => {
|
|
it('should have correct default status code and code', () => {
|
|
const error = new AIServiceError('AI operation failed');
|
|
expect(error.statusCode).toBe(500);
|
|
expect(error.code).toBe('AI_SERVICE_ERROR');
|
|
});
|
|
|
|
it('should allow custom status code', () => {
|
|
const error = new AIServiceError('Rate limited', 429);
|
|
expect(error.statusCode).toBe(429);
|
|
});
|
|
});
|
|
|
|
describe('DatabaseError', () => {
|
|
it('should have correct default status code and code', () => {
|
|
const error = new DatabaseError('Query failed');
|
|
expect(error.statusCode).toBe(500);
|
|
expect(error.code).toBe('DATABASE_ERROR');
|
|
});
|
|
|
|
it('should allow custom status code', () => {
|
|
const error = new DatabaseError('Connection timeout', 503);
|
|
expect(error.statusCode).toBe(503);
|
|
});
|
|
});
|
|
|
|
describe('ConfigurationError', () => {
|
|
it('should have correct status code and code', () => {
|
|
const error = new ConfigurationError('Missing API key');
|
|
expect(error.statusCode).toBe(500);
|
|
expect(error.code).toBe('CONFIGURATION_ERROR');
|
|
expect(error.name).toBe('ConfigurationError');
|
|
});
|
|
});
|
|
|
|
describe('isApiError', () => {
|
|
it('should return true for ApiError instances', () => {
|
|
expect(isApiError(new ApiError('test', 500))).toBe(true);
|
|
expect(isApiError(new ValidationError('test'))).toBe(true);
|
|
expect(isApiError(new AuthorizationError())).toBe(true);
|
|
expect(isApiError(new ForbiddenError())).toBe(true);
|
|
expect(isApiError(new NotFoundError())).toBe(true);
|
|
expect(isApiError(new ExternalServiceError('test', 'service'))).toBe(true);
|
|
expect(isApiError(new LlamaCloudConnectionError())).toBe(true);
|
|
expect(isApiError(new AIServiceError('test'))).toBe(true);
|
|
expect(isApiError(new DatabaseError('test'))).toBe(true);
|
|
expect(isApiError(new ConfigurationError('test'))).toBe(true);
|
|
});
|
|
|
|
it('should return false for regular Error', () => {
|
|
expect(isApiError(new Error('test'))).toBe(false);
|
|
});
|
|
|
|
it('should return false for non-error values', () => {
|
|
expect(isApiError(null)).toBe(false);
|
|
expect(isApiError(undefined)).toBe(false);
|
|
expect(isApiError('error string')).toBe(false);
|
|
expect(isApiError({ message: 'error object' })).toBe(false);
|
|
expect(isApiError(123)).toBe(false);
|
|
});
|
|
});
|