more backend unit test coverage

This commit is contained in:
jackiettran
2026-01-18 19:18:35 -05:00
parent e6c56ae90f
commit 41d8cf4c04
18 changed files with 4961 additions and 1 deletions

View File

@@ -0,0 +1,184 @@
// Mock dependencies before requiring the service
jest.mock('../../../models', () => ({
sequelize: {
query: jest.fn(),
},
}));
jest.mock('sequelize', () => ({
QueryTypes: {
SELECT: 'SELECT',
},
}));
jest.mock('../../../utils/logger', () => ({
info: jest.fn(),
error: jest.fn(),
warn: jest.fn(),
}));
const { sequelize } = require('../../../models');
const locationService = require('../../../services/locationService');
describe('LocationService', () => {
beforeEach(() => {
jest.clearAllMocks();
});
describe('findUsersInRadius', () => {
it('should find users within specified radius', async () => {
const mockUsers = [
{ id: 'user-1', email: 'user1@test.com', firstName: 'User', lastName: 'One', latitude: '37.7749', longitude: '-122.4194', distance: '1.5' },
{ id: 'user-2', email: 'user2@test.com', firstName: 'User', lastName: 'Two', latitude: '37.7849', longitude: '-122.4094', distance: '2.3' },
];
sequelize.query.mockResolvedValue(mockUsers);
const result = await locationService.findUsersInRadius(37.7749, -122.4194, 10);
expect(result).toHaveLength(2);
expect(result[0]).toMatchObject({
id: 'user-1',
email: 'user1@test.com',
firstName: 'User',
lastName: 'One',
});
expect(parseFloat(result[0].distance)).toBeCloseTo(1.5, 1);
});
it('should use default radius of 10 miles', async () => {
sequelize.query.mockResolvedValue([]);
await locationService.findUsersInRadius(37.7749, -122.4194);
expect(sequelize.query).toHaveBeenCalledWith(
expect.any(String),
expect.objectContaining({
replacements: expect.objectContaining({
radiusMiles: 10,
}),
})
);
});
it('should throw error when latitude is missing', async () => {
await expect(locationService.findUsersInRadius(null, -122.4194, 10))
.rejects.toThrow('Latitude and longitude are required');
});
it('should throw error when longitude is missing', async () => {
await expect(locationService.findUsersInRadius(37.7749, null, 10))
.rejects.toThrow('Latitude and longitude are required');
});
it('should throw error when radius is zero', async () => {
await expect(locationService.findUsersInRadius(37.7749, -122.4194, 0))
.rejects.toThrow('Radius must be between 1 and 100 miles');
});
it('should throw error when radius is negative', async () => {
await expect(locationService.findUsersInRadius(37.7749, -122.4194, -5))
.rejects.toThrow('Radius must be between 1 and 100 miles');
});
it('should throw error when radius exceeds 100 miles', async () => {
await expect(locationService.findUsersInRadius(37.7749, -122.4194, 150))
.rejects.toThrow('Radius must be between 1 and 100 miles');
});
it('should handle database errors', async () => {
sequelize.query.mockRejectedValue(new Error('Database error'));
await expect(locationService.findUsersInRadius(37.7749, -122.4194, 10))
.rejects.toThrow('Failed to find users in radius');
});
it('should return empty array when no users found', async () => {
sequelize.query.mockResolvedValue([]);
const result = await locationService.findUsersInRadius(37.7749, -122.4194, 10);
expect(result).toEqual([]);
});
it('should format distance to 2 decimal places', async () => {
const mockUsers = [
{ id: 'user-1', email: 'user1@test.com', firstName: 'User', lastName: 'One', latitude: '37.7749', longitude: '-122.4194', distance: '1.23456789' },
];
sequelize.query.mockResolvedValue(mockUsers);
const result = await locationService.findUsersInRadius(37.7749, -122.4194, 10);
expect(result[0].distance).toBe('1.23');
});
});
describe('calculateDistance', () => {
it('should calculate distance between two points', () => {
// San Francisco to Los Angeles: approximately 347 miles
const distance = locationService.calculateDistance(
37.7749, -122.4194, // San Francisco
34.0522, -118.2437 // Los Angeles
);
expect(distance).toBeGreaterThan(340);
expect(distance).toBeLessThan(360);
});
it('should return 0 for same coordinates', () => {
const distance = locationService.calculateDistance(
37.7749, -122.4194,
37.7749, -122.4194
);
expect(distance).toBe(0);
});
it('should calculate short distances accurately', () => {
// Two points about 1 mile apart
const distance = locationService.calculateDistance(
37.7749, -122.4194,
37.7893, -122.4094
);
expect(distance).toBeGreaterThan(0.5);
expect(distance).toBeLessThan(2);
});
it('should handle negative coordinates', () => {
// Sydney, Australia to Melbourne, Australia
const distance = locationService.calculateDistance(
-33.8688, 151.2093, // Sydney
-37.8136, 144.9631 // Melbourne
);
expect(distance).toBeGreaterThan(400);
expect(distance).toBeLessThan(500);
});
it('should handle crossing the prime meridian', () => {
// London to Paris
const distance = locationService.calculateDistance(
51.5074, -0.1278, // London
48.8566, 2.3522 // Paris
);
expect(distance).toBeGreaterThan(200);
expect(distance).toBeLessThan(250);
});
});
describe('toRadians', () => {
it('should convert degrees to radians', () => {
expect(locationService.toRadians(0)).toBe(0);
expect(locationService.toRadians(180)).toBeCloseTo(Math.PI, 5);
expect(locationService.toRadians(90)).toBeCloseTo(Math.PI / 2, 5);
expect(locationService.toRadians(360)).toBeCloseTo(2 * Math.PI, 5);
});
it('should handle negative degrees', () => {
expect(locationService.toRadians(-90)).toBeCloseTo(-Math.PI / 2, 5);
});
});
});