379 lines
14 KiB
TypeScript
379 lines
14 KiB
TypeScript
import { describe, it, expect } from 'vitest';
|
|
import { validateVehicle } from '../validation';
|
|
|
|
describe('Vehicle Validation', () => {
|
|
describe('validateVehicle', () => {
|
|
const validVehicleData = {
|
|
plateNumber: 'ABC-123',
|
|
bodyType: 'سيدان',
|
|
manufacturer: 'تويوتا',
|
|
model: 'كامري',
|
|
year: 2020,
|
|
transmission: 'Automatic',
|
|
fuel: 'Gasoline',
|
|
useType: 'personal',
|
|
ownerId: 1,
|
|
};
|
|
|
|
it('should validate a complete valid vehicle', () => {
|
|
const result = validateVehicle(validVehicleData);
|
|
|
|
expect(result.isValid).toBe(true);
|
|
expect(Object.keys(result.errors)).toHaveLength(0);
|
|
});
|
|
|
|
it('should validate a minimal valid vehicle', () => {
|
|
const minimalData = {
|
|
plateNumber: 'ABC-123',
|
|
bodyType: 'سيدان',
|
|
manufacturer: 'تويوتا',
|
|
model: 'كامري',
|
|
year: 2020,
|
|
transmission: 'Automatic',
|
|
fuel: 'Gasoline',
|
|
useType: 'personal',
|
|
ownerId: 1,
|
|
};
|
|
|
|
const result = validateVehicle(minimalData);
|
|
|
|
expect(result.isValid).toBe(true);
|
|
expect(Object.keys(result.errors)).toHaveLength(0);
|
|
});
|
|
|
|
describe('plateNumber validation', () => {
|
|
it('should require plate number', () => {
|
|
const result = validateVehicle({ ...validVehicleData, plateNumber: '' });
|
|
|
|
expect(result.isValid).toBe(false);
|
|
expect(result.errors.plateNumber).toBe('رقم اللوحة مطلوب');
|
|
});
|
|
|
|
it('should require plate number to not be just whitespace', () => {
|
|
const result = validateVehicle({ ...validVehicleData, plateNumber: ' ' });
|
|
|
|
expect(result.isValid).toBe(false);
|
|
expect(result.errors.plateNumber).toBe('رقم اللوحة مطلوب');
|
|
});
|
|
});
|
|
|
|
describe('bodyType validation', () => {
|
|
it('should require body type', () => {
|
|
const result = validateVehicle({ ...validVehicleData, bodyType: '' });
|
|
|
|
expect(result.isValid).toBe(false);
|
|
expect(result.errors.bodyType).toBe('نوع الهيكل مطلوب');
|
|
});
|
|
|
|
it('should require body type to not be just whitespace', () => {
|
|
const result = validateVehicle({ ...validVehicleData, bodyType: ' ' });
|
|
|
|
expect(result.isValid).toBe(false);
|
|
expect(result.errors.bodyType).toBe('نوع الهيكل مطلوب');
|
|
});
|
|
});
|
|
|
|
describe('manufacturer validation', () => {
|
|
it('should require manufacturer', () => {
|
|
const result = validateVehicle({ ...validVehicleData, manufacturer: '' });
|
|
|
|
expect(result.isValid).toBe(false);
|
|
expect(result.errors.manufacturer).toBe('الشركة المصنعة مطلوبة');
|
|
});
|
|
|
|
it('should require manufacturer to not be just whitespace', () => {
|
|
const result = validateVehicle({ ...validVehicleData, manufacturer: ' ' });
|
|
|
|
expect(result.isValid).toBe(false);
|
|
expect(result.errors.manufacturer).toBe('الشركة المصنعة مطلوبة');
|
|
});
|
|
});
|
|
|
|
describe('model validation', () => {
|
|
it('should require model', () => {
|
|
const result = validateVehicle({ ...validVehicleData, model: '' });
|
|
|
|
expect(result.isValid).toBe(false);
|
|
expect(result.errors.model).toBe('الموديل مطلوب');
|
|
});
|
|
|
|
it('should require model to not be just whitespace', () => {
|
|
const result = validateVehicle({ ...validVehicleData, model: ' ' });
|
|
|
|
expect(result.isValid).toBe(false);
|
|
expect(result.errors.model).toBe('الموديل مطلوب');
|
|
});
|
|
});
|
|
|
|
describe('year validation', () => {
|
|
it('should not validate undefined year (partial validation)', () => {
|
|
const result = validateVehicle({ ...validVehicleData, year: undefined as any });
|
|
|
|
expect(result.isValid).toBe(true);
|
|
expect(result.errors.year).toBeUndefined();
|
|
});
|
|
|
|
it('should reject year below minimum', () => {
|
|
const result = validateVehicle({ ...validVehicleData, year: 1989 });
|
|
|
|
expect(result.isValid).toBe(false);
|
|
expect(result.errors.year).toContain('السنة يجب أن تكون بين 1990');
|
|
});
|
|
|
|
it('should reject year above maximum', () => {
|
|
const currentYear = new Date().getFullYear();
|
|
const result = validateVehicle({ ...validVehicleData, year: currentYear + 2 });
|
|
|
|
expect(result.isValid).toBe(false);
|
|
expect(result.errors.year).toContain('السنة يجب أن تكون بين');
|
|
});
|
|
|
|
it('should accept current year', () => {
|
|
const currentYear = new Date().getFullYear();
|
|
const result = validateVehicle({ ...validVehicleData, year: currentYear });
|
|
|
|
expect(result.isValid).toBe(true);
|
|
});
|
|
|
|
it('should accept next year', () => {
|
|
const nextYear = new Date().getFullYear() + 1;
|
|
const result = validateVehicle({ ...validVehicleData, year: nextYear });
|
|
|
|
expect(result.isValid).toBe(true);
|
|
});
|
|
});
|
|
|
|
describe('transmission validation', () => {
|
|
it('should require transmission', () => {
|
|
const result = validateVehicle({ ...validVehicleData, transmission: '' });
|
|
|
|
expect(result.isValid).toBe(false);
|
|
expect(result.errors.transmission).toBe('نوع ناقل الحركة غير صحيح');
|
|
});
|
|
|
|
it('should accept valid transmission types', () => {
|
|
const automaticResult = validateVehicle({ ...validVehicleData, transmission: 'Automatic' });
|
|
const manualResult = validateVehicle({ ...validVehicleData, transmission: 'Manual' });
|
|
|
|
expect(automaticResult.isValid).toBe(true);
|
|
expect(manualResult.isValid).toBe(true);
|
|
});
|
|
|
|
it('should reject invalid transmission types', () => {
|
|
const result = validateVehicle({ ...validVehicleData, transmission: 'CVT' });
|
|
|
|
expect(result.isValid).toBe(false);
|
|
expect(result.errors.transmission).toBe('نوع ناقل الحركة غير صحيح');
|
|
});
|
|
});
|
|
|
|
describe('fuel validation', () => {
|
|
it('should require fuel type', () => {
|
|
const result = validateVehicle({ ...validVehicleData, fuel: '' });
|
|
|
|
expect(result.isValid).toBe(false);
|
|
expect(result.errors.fuel).toBe('نوع الوقود غير صحيح');
|
|
});
|
|
|
|
it('should accept valid fuel types', () => {
|
|
const validFuels = ['Gasoline', 'Diesel', 'Hybrid', 'Mild Hybrid', 'Electric'];
|
|
|
|
validFuels.forEach(fuel => {
|
|
const result = validateVehicle({ ...validVehicleData, fuel });
|
|
expect(result.isValid).toBe(true);
|
|
});
|
|
});
|
|
|
|
it('should reject invalid fuel types', () => {
|
|
const result = validateVehicle({ ...validVehicleData, fuel: 'Nuclear' });
|
|
|
|
expect(result.isValid).toBe(false);
|
|
expect(result.errors.fuel).toBe('نوع الوقود غير صحيح');
|
|
});
|
|
});
|
|
|
|
describe('cylinders validation', () => {
|
|
it('should accept valid cylinder counts', () => {
|
|
const validCylinders = [1, 2, 3, 4, 6, 8, 10, 12];
|
|
|
|
validCylinders.forEach(cylinders => {
|
|
const result = validateVehicle({ ...validVehicleData, cylinders });
|
|
expect(result.isValid).toBe(true);
|
|
});
|
|
});
|
|
|
|
it('should reject cylinder count below minimum', () => {
|
|
const result = validateVehicle({ ...validVehicleData, cylinders: 0 });
|
|
|
|
expect(result.isValid).toBe(false);
|
|
expect(result.errors.cylinders).toContain('عدد الأسطوانات يجب أن يكون بين 1');
|
|
});
|
|
|
|
it('should reject cylinder count above maximum', () => {
|
|
const result = validateVehicle({ ...validVehicleData, cylinders: 16 });
|
|
|
|
expect(result.isValid).toBe(false);
|
|
expect(result.errors.cylinders).toContain('عدد الأسطوانات يجب أن يكون بين 1 و 12');
|
|
});
|
|
|
|
it('should accept null/undefined cylinders', () => {
|
|
const result1 = validateVehicle({ ...validVehicleData, cylinders: undefined });
|
|
const result2 = validateVehicle({ ...validVehicleData, cylinders: null as any });
|
|
|
|
expect(result1.isValid).toBe(true);
|
|
expect(result2.isValid).toBe(true);
|
|
});
|
|
});
|
|
|
|
describe('engineDisplacement validation', () => {
|
|
it('should accept valid engine displacements', () => {
|
|
const validDisplacements = [1.0, 1.5, 2.0, 2.5, 3.0, 4.0, 5.0];
|
|
|
|
validDisplacements.forEach(engineDisplacement => {
|
|
const result = validateVehicle({ ...validVehicleData, engineDisplacement });
|
|
expect(result.isValid).toBe(true);
|
|
});
|
|
});
|
|
|
|
it('should reject engine displacement at zero', () => {
|
|
const result = validateVehicle({ ...validVehicleData, engineDisplacement: 0 });
|
|
|
|
expect(result.isValid).toBe(false);
|
|
expect(result.errors.engineDisplacement).toContain('سعة المحرك يجب أن تكون بين 0.1');
|
|
});
|
|
|
|
it('should reject engine displacement above maximum', () => {
|
|
const result = validateVehicle({ ...validVehicleData, engineDisplacement: 15.0 });
|
|
|
|
expect(result.isValid).toBe(false);
|
|
expect(result.errors.engineDisplacement).toContain('سعة المحرك يجب أن تكون بين 0.1 و 10');
|
|
});
|
|
|
|
it('should accept null/undefined engine displacement', () => {
|
|
const result1 = validateVehicle({ ...validVehicleData, engineDisplacement: undefined });
|
|
const result2 = validateVehicle({ ...validVehicleData, engineDisplacement: null as any });
|
|
|
|
expect(result1.isValid).toBe(true);
|
|
expect(result2.isValid).toBe(true);
|
|
});
|
|
});
|
|
|
|
describe('useType validation', () => {
|
|
it('should require use type', () => {
|
|
const result = validateVehicle({ ...validVehicleData, useType: '' });
|
|
|
|
expect(result.isValid).toBe(false);
|
|
expect(result.errors.useType).toBe('نوع الاستخدام غير صحيح');
|
|
});
|
|
|
|
it('should accept valid use types', () => {
|
|
const validUseTypes = ['personal', 'taxi', 'apps', 'loading', 'travel'];
|
|
|
|
validUseTypes.forEach(useType => {
|
|
const result = validateVehicle({ ...validVehicleData, useType });
|
|
expect(result.isValid).toBe(true);
|
|
});
|
|
});
|
|
|
|
it('should reject invalid use types', () => {
|
|
const result = validateVehicle({ ...validVehicleData, useType: 'military' });
|
|
|
|
expect(result.isValid).toBe(false);
|
|
expect(result.errors.useType).toBe('نوع الاستخدام غير صحيح');
|
|
});
|
|
});
|
|
|
|
describe('ownerId validation', () => {
|
|
it('should not validate undefined owner ID (partial validation)', () => {
|
|
const result = validateVehicle({ ...validVehicleData, ownerId: undefined as any });
|
|
|
|
expect(result.isValid).toBe(true);
|
|
expect(result.errors.ownerId).toBeUndefined();
|
|
});
|
|
|
|
it('should reject zero owner ID', () => {
|
|
const result = validateVehicle({ ...validVehicleData, ownerId: 0 });
|
|
|
|
expect(result.isValid).toBe(false);
|
|
expect(result.errors.ownerId).toBe('مالك المركبة مطلوب');
|
|
});
|
|
|
|
it('should reject negative owner ID', () => {
|
|
const result = validateVehicle({ ...validVehicleData, ownerId: -1 });
|
|
|
|
expect(result.isValid).toBe(false);
|
|
expect(result.errors.ownerId).toBe('مالك المركبة مطلوب');
|
|
});
|
|
|
|
it('should accept positive owner ID', () => {
|
|
const result = validateVehicle({ ...validVehicleData, ownerId: 5 });
|
|
|
|
expect(result.isValid).toBe(true);
|
|
});
|
|
});
|
|
|
|
describe('multiple validation errors', () => {
|
|
it('should return all validation errors', () => {
|
|
const invalidData = {
|
|
plateNumber: '',
|
|
bodyType: '',
|
|
manufacturer: '',
|
|
model: '',
|
|
year: 1980,
|
|
transmission: 'Invalid',
|
|
fuel: 'Invalid',
|
|
cylinders: 20,
|
|
engineDisplacement: 15.0,
|
|
useType: 'Invalid',
|
|
ownerId: 0,
|
|
};
|
|
|
|
const result = validateVehicle(invalidData);
|
|
|
|
expect(result.isValid).toBe(false);
|
|
expect(Object.keys(result.errors)).toContain('plateNumber');
|
|
expect(Object.keys(result.errors)).toContain('bodyType');
|
|
expect(Object.keys(result.errors)).toContain('manufacturer');
|
|
expect(Object.keys(result.errors)).toContain('model');
|
|
expect(Object.keys(result.errors)).toContain('year');
|
|
expect(Object.keys(result.errors)).toContain('transmission');
|
|
expect(Object.keys(result.errors)).toContain('fuel');
|
|
expect(Object.keys(result.errors)).toContain('cylinders');
|
|
expect(Object.keys(result.errors)).toContain('engineDisplacement');
|
|
expect(Object.keys(result.errors)).toContain('useType');
|
|
expect(Object.keys(result.errors)).toContain('ownerId');
|
|
});
|
|
});
|
|
|
|
describe('partial validation', () => {
|
|
it('should validate only provided fields', () => {
|
|
const partialData = {
|
|
plateNumber: 'XYZ-789',
|
|
year: 2021,
|
|
};
|
|
|
|
const result = validateVehicle(partialData);
|
|
|
|
expect(result.isValid).toBe(true);
|
|
expect(Object.keys(result.errors)).toHaveLength(0);
|
|
});
|
|
|
|
it('should validate only provided fields with errors', () => {
|
|
const partialData = {
|
|
plateNumber: '',
|
|
year: 1980,
|
|
cylinders: 20,
|
|
};
|
|
|
|
const result = validateVehicle(partialData);
|
|
|
|
expect(result.isValid).toBe(false);
|
|
expect(Object.keys(result.errors)).toContain('plateNumber');
|
|
expect(Object.keys(result.errors)).toContain('year');
|
|
expect(Object.keys(result.errors)).toContain('cylinders');
|
|
expect(Object.keys(result.errors)).not.toContain('manufacturer');
|
|
expect(Object.keys(result.errors)).not.toContain('model');
|
|
});
|
|
});
|
|
});
|
|
}); |