import { describe, it, expect, beforeEach, afterEach } from 'vitest'; import Cycle from '../Cycle.js'; import { query } from '../../database/db.js'; describe('Cycle Model', () => { // Clean up test data before and after each test beforeEach(async () => { await query('DELETE FROM cycles WHERE id LIKE $1', ['TEST-%']); }); afterEach(async () => { await query('DELETE FROM cycles WHERE id LIKE $1', ['TEST-%']); }); describe('create', () => { it('should create a new cycle with all fields', async () => { const cycleData = { id: 'TEST-CYCLE-001', totalDays: 35, currentDay: 1, startDate: '2026-04-01', chickInWeight: 40, docInCount: 10000, status: 'Active', }; const cycle = await Cycle.create(cycleData); expect(cycle).toBeDefined(); expect(cycle.id).toBe('TEST-CYCLE-001'); expect(cycle.totalDays).toBe(35); expect(cycle.currentDay).toBeGreaterThanOrEqual(1); expect(cycle.docInCount).toBe(10000); expect(cycle.status).toBe('Active'); }); it('should create a cycle with optional fields as null', async () => { const cycleData = { id: 'TEST-CYCLE-002', totalDays: 35, currentDay: 0, startDate: '2026-05-01', status: 'Upcoming', }; const cycle = await Cycle.create(cycleData); expect(cycle).toBeDefined(); expect(cycle.id).toBe('TEST-CYCLE-002'); expect(cycle.chickInWeight).toBeNull(); expect(cycle.docInCount).toBeNull(); expect(cycle.endDate).toBeNull(); }); }); describe('getById', () => { it('should retrieve a cycle by ID', async () => { // Create test cycle await Cycle.create({ id: 'TEST-CYCLE-003', totalDays: 35, currentDay: 5, startDate: '2026-04-01', status: 'Active', }); const cycle = await Cycle.getById('TEST-CYCLE-003'); expect(cycle).toBeDefined(); expect(cycle.id).toBe('TEST-CYCLE-003'); expect(cycle.totalDays).toBe(35); }); it('should return null for non-existent cycle', async () => { const cycle = await Cycle.getById('DOES-NOT-EXIST'); expect(cycle).toBeNull(); }); }); describe('getAll', () => { it('should retrieve all cycles ordered by start date', async () => { // Create multiple test cycles await Cycle.create({ id: 'TEST-CYCLE-004', totalDays: 35, currentDay: 1, startDate: '2026-04-01', status: 'Active', }); await Cycle.create({ id: 'TEST-CYCLE-005', totalDays: 35, currentDay: 0, startDate: '2026-05-01', status: 'Upcoming', }); const cycles = await Cycle.getAll(); const testCycles = cycles.filter((c) => c.id.startsWith('TEST-')); expect(testCycles.length).toBeGreaterThanOrEqual(2); // Verify ordering (most recent start date first) const testCycle005 = testCycles.find((c) => c.id === 'TEST-CYCLE-005'); const testCycle004 = testCycles.find((c) => c.id === 'TEST-CYCLE-004'); expect(testCycles.indexOf(testCycle005)).toBeLessThan(testCycles.indexOf(testCycle004)); }); }); describe('update', () => { it('should update an existing cycle', async () => { // Create initial cycle await Cycle.create({ id: 'TEST-CYCLE-006', totalDays: 35, currentDay: 5, startDate: '2026-04-01', status: 'Active', docInCount: 10000, }); // Update the cycle const updated = await Cycle.update('TEST-CYCLE-006', { totalDays: 40, currentDay: 10, startDate: '2026-04-01', status: 'Active', docInCount: 9500, }); expect(updated).toBeDefined(); expect(updated.totalDays).toBe(40); expect(updated.docInCount).toBe(9500); }); it('should return null when updating non-existent cycle', async () => { const result = await Cycle.update('DOES-NOT-EXIST', { totalDays: 35, currentDay: 1, startDate: '2026-04-01', status: 'Active', }); expect(result).toBeNull(); }); }); describe('delete', () => { it('should delete an existing cycle', async () => { // Create cycle to delete await Cycle.create({ id: 'TEST-CYCLE-007', totalDays: 35, currentDay: 1, startDate: '2026-04-01', status: 'Active', }); const deleted = await Cycle.delete('TEST-CYCLE-007'); expect(deleted).toBe(true); // Verify it's gone const cycle = await Cycle.getById('TEST-CYCLE-007'); expect(cycle).toBeNull(); }); it('should return false when deleting non-existent cycle', async () => { const deleted = await Cycle.delete('DOES-NOT-EXIST'); expect(deleted).toBe(false); }); }); describe('getActive', () => { it('should retrieve the active cycle', async () => { // Create an active cycle await Cycle.create({ id: 'TEST-CYCLE-008', totalDays: 35, currentDay: 10, startDate: '2026-04-01', status: 'Active', }); const activeCycle = await Cycle.getActive(); // Should return either our test cycle or another active cycle expect(activeCycle).toBeDefined(); expect(activeCycle.status).toBe('Active'); }); }); describe('formatCycle', () => { it('should calculate current day dynamically for active cycles', () => { const today = new Date(); const startDate = new Date(today); startDate.setDate(startDate.getDate() - 10); // 10 days ago const rawCycle = { id: 'TEST-FORMAT', total_days: 35, current_day: 1, start_date: startDate.toISOString().split('T')[0], end_date: null, chick_in_weight: 40, doc_in_count: 10000, status: 'Active', created_at: new Date(), updated_at: new Date(), }; const formatted = Cycle.formatCycle(rawCycle); expect(formatted.currentDay).toBe(10); expect(formatted.id).toBe('TEST-FORMAT'); expect(formatted.status).toBe('Active'); }); it('should not calculate current day for completed cycles', () => { const rawCycle = { id: 'TEST-FORMAT-2', total_days: 35, current_day: 35, start_date: '2026-03-01', end_date: '2026-04-05', chick_in_weight: 40, doc_in_count: 10000, status: 'Completed', created_at: new Date(), updated_at: new Date(), }; const formatted = Cycle.formatCycle(rawCycle); expect(formatted.currentDay).toBe(35); expect(formatted.status).toBe('Completed'); }); }); });