const ConditionCheckService = require('../../../services/conditionCheckService'); const { ConditionCheck, Rental, User } = require('../../../models'); jest.mock('../../../models'); describe('ConditionCheckService', () => { beforeEach(() => { jest.clearAllMocks(); }); describe('submitConditionCheck', () => { // Set rental dates relative to current time for valid time window // Active status is computed: confirmed + startDateTime in the past const now = new Date(); const mockRental = { id: 'rental-123', ownerId: 'owner-456', renterId: 'renter-789', startDateTime: new Date(now.getTime() - 1000 * 60 * 60), // 1 hour ago endDateTime: new Date(now.getTime() + 1000 * 60 * 60 * 24), // 24 hours from now status: 'confirmed' // Will be computed as "active" since startDateTime is in the past }; const mockPhotos = ['/uploads/photo1.jpg', '/uploads/photo2.jpg']; beforeEach(() => { Rental.findByPk.mockResolvedValue(mockRental); ConditionCheck.findOne.mockResolvedValue(null); // No existing check ConditionCheck.create.mockResolvedValue({ id: 'check-123', rentalId: 'rental-123', checkType: 'rental_start_renter', photos: mockPhotos, notes: 'Item received in good condition', submittedBy: 'renter-789' }); }); it('should submit condition check with photos and notes', async () => { const result = await ConditionCheckService.submitConditionCheck( 'rental-123', 'rental_start_renter', 'renter-789', mockPhotos, 'Item received in good condition' ); expect(ConditionCheck.create).toHaveBeenCalledWith( expect.objectContaining({ rentalId: 'rental-123', checkType: 'rental_start_renter', submittedBy: 'renter-789', imageFilenames: mockPhotos, notes: 'Item received in good condition', }) ); expect(result).toBeTruthy(); expect(result.id).toBe('check-123'); }); it('should validate user authorization - owner checks', async () => { // Renter trying to submit pre-rental owner check await expect( ConditionCheckService.submitConditionCheck( 'rental-123', 'pre_rental_owner', 'renter-789', mockPhotos ) ).rejects.toThrow('Only the item owner can submit owner condition checks'); }); it('should validate user authorization - renter checks', async () => { // Owner trying to submit rental start renter check await expect( ConditionCheckService.submitConditionCheck( 'rental-123', 'rental_start_renter', 'owner-456', mockPhotos ) ).rejects.toThrow('Only the renter can submit renter condition checks'); }); it('should prevent duplicate condition checks', async () => { ConditionCheck.findOne.mockResolvedValue({ id: 'existing-check' }); await expect( ConditionCheckService.submitConditionCheck( 'rental-123', 'rental_start_renter', 'renter-789', mockPhotos ) ).rejects.toThrow('Condition check already submitted for this type'); }); it('should limit number of photos to 20', async () => { const tooManyPhotos = Array(21).fill('/uploads/photo.jpg'); await expect( ConditionCheckService.submitConditionCheck( 'rental-123', 'rental_start_renter', 'renter-789', tooManyPhotos ) ).rejects.toThrow('Maximum 20 photos allowed per condition check'); }); it('should handle rental not found', async () => { Rental.findByPk.mockResolvedValue(null); await expect( ConditionCheckService.submitConditionCheck( 'nonexistent-rental', 'rental_start_renter', 'renter-789', mockPhotos ) ).rejects.toThrow('Rental not found'); }); }); });