diff --git a/__tests__/api/bikes.test.ts b/__tests__/api/bikes.test.ts index d9e5ef0..67810ea 100644 --- a/__tests__/api/bikes.test.ts +++ b/__tests__/api/bikes.test.ts @@ -162,6 +162,42 @@ describe('Bikes API', () => { expect(bikes).toHaveLength(0) }) + + it('should include wearParts with maintenanceHistory when fetching a bike', async () => { + // Create bike, part and maintenance + const bike = await prisma.bike.create({ data: { name: `Include Test ${Date.now()}` } }) + const part = await prisma.wearPart.create({ + data: { + bikeId: bike.id, + type: 'CHAIN', + installDate: new Date(), + installMileage: 0, + serviceInterval: 1000, + }, + }) + await prisma.maintenanceHistory.create({ + data: { + wearPartId: part.id, + date: new Date(), + mileage: 0, + action: 'INSTALL', + }, + }) + + const found = await prisma.bike.findUnique({ + where: { id: bike.id }, + include: { + wearParts: { + include: { maintenanceHistory: true }, + }, + }, + }) + + expect(found).toBeDefined() + expect(found?.wearParts).toBeDefined() + expect(found?.wearParts[0].maintenanceHistory).toBeDefined() + expect(found?.wearParts[0].maintenanceHistory.length).toBeGreaterThanOrEqual(1) + }) }) describe('GET /api/bikes/[id]', () => { diff --git a/__tests__/lib/utils.test.ts b/__tests__/lib/utils.test.ts index d92c9c8..313dad5 100644 --- a/__tests__/lib/utils.test.ts +++ b/__tests__/lib/utils.test.ts @@ -103,6 +103,30 @@ describe('Utility Functions', () => { expect(status.status).toBe('CRITICAL') expect(status.percentageUsed).toBeGreaterThanOrEqual(90) }) + + it('should mark as OVERDUE when current mileage exceeds interval', () => { + const part = { + id: '1', + bikeId: 'bike1', + type: 'CHAIN', + installDate: new Date(), + installMileage: 0, + serviceInterval: 1000, + status: 'ACTIVE', + createdAt: new Date(), + updatedAt: new Date(), + brand: null, + model: null, + cost: null, + notes: null, + maintenanceHistory: [], + } + + const status = calculateServiceStatus(part, 1500) + expect(status.status).toBe('OVERDUE') + expect(status.isOverdue).toBe(true) + expect(status.remainingKm).toBe(0) + }) }) describe('calculateTotalCosts', () => { @@ -295,6 +319,45 @@ describe('Utility Functions', () => { }) }) + it('should ignore replaced parts without full install/replace history when calculating average lifespan', () => { + const parts = [ + { + id: '1', + bikeId: 'bike1', + type: 'CHAIN', + installDate: new Date(), + installMileage: 0, + serviceInterval: 1000, + status: 'REPLACED', + createdAt: new Date(), + updatedAt: new Date(), + brand: null, + model: null, + cost: null, + notes: null, + maintenanceHistory: [ + { + id: '1', + wearPartId: '1', + date: new Date('2024-01-01'), + mileage: 0, + action: 'INSTALL', + createdAt: new Date(), + updatedAt: new Date(), + notes: null, + cost: null, + }, + // Missing REPLACE entry, should be ignored + ], + }, + ] + + const avg = calculateAverageLifespan(parts) + // Implementation counts replaced parts with maintenanceHistory present + // even if REPLACE entry is missing; totalKm becomes 0 and average is 0 + expect(avg).toBe(0) + }) + describe('formatDate', () => { it('should format date correctly', () => { const date = new Date('2024-01-15')