import { fireEvent, render, screen, waitFor } from '@testing-library/react'; import { beforeEach, describe, expect, it, vi } from 'vitest'; import SettingsPage from '../SettingsPage.tsx'; const { createKandangMock, createFlockMock, createCycleMock, updateCycleMock, reloadMock, farmState } = vi.hoisted( () => ({ createKandangMock: vi.fn(), createFlockMock: vi.fn(), createCycleMock: vi.fn(), updateCycleMock: vi.fn(), reloadMock: vi.fn().mockResolvedValue(undefined), farmState: { sites: [{ id: 7, site_name: 'Site A', user: 99, created_at: '', updated_at: '' }], kandangs: [] as Array<{ id: number; kandang_name: string; site: number; created_at: string; updated_at: string; }>, flocks: [] as Array<{ id: number; flock_name: string; kandang: number; created_at: string; updated_at: string; }>, cycles: [] as unknown[], selectedSiteId: 7, selectedKandangId: null as number | null, selectedCycleId: null as number | null, selectedCycle: null as unknown, }, }) ); vi.mock('../../services/apiClient.ts', () => ({ api: { sites: { create: vi.fn(), remove: vi.fn(), }, kandangs: { create: createKandangMock, remove: vi.fn(), }, flocks: { create: createFlockMock, remove: vi.fn(), }, cycles: { create: createCycleMock, update: updateCycleMock, remove: vi.fn(), }, }, errorMessage: (err: unknown) => (err instanceof Error ? err.message : 'Terjadi kesalahan'), })); vi.mock('../../context/AuthContext.tsx', () => ({ useAuth: () => ({ user: { id: 99, user_name: 'tester', status: 'superadmin', created_at: '', updated_at: '', }, }), })); vi.mock('../../context/FarmContext.tsx', () => ({ useFarm: () => ({ sites: farmState.sites, kandangs: farmState.kandangs, flocks: farmState.flocks, cycles: farmState.cycles, selectedSiteId: farmState.selectedSiteId, selectedKandangId: farmState.selectedKandangId, selectedCycleId: farmState.selectedCycleId, selectedCycle: farmState.selectedCycle, reload: reloadMock, setSelectedSiteId: vi.fn(), setSelectedKandangId: vi.fn(), setSelectedCycleId: vi.fn(), }), })); describe('SettingsPage settings forms', () => { beforeEach(() => { createKandangMock.mockReset(); createFlockMock.mockReset(); createCycleMock.mockReset(); updateCycleMock.mockReset(); reloadMock.mockClear(); farmState.kandangs = []; farmState.flocks = []; farmState.cycles = []; farmState.selectedSiteId = 7; farmState.selectedKandangId = null; farmState.selectedCycleId = null; farmState.selectedCycle = null; createKandangMock.mockResolvedValue({ id: 11, kandang_name: 'Kandang 1', site: 7, created_at: '', updated_at: '', }); createFlockMock.mockResolvedValue({ id: 3, flock_name: 'Lantai 1', kandang: 11, created_at: '', updated_at: '', }); createCycleMock.mockResolvedValue({ id: 21, kandang: 11, total_days: 35, current_day: 1, start_date: '2026-08-18', end_date: '2026-09-21', chick_in_weight: 35, doc_in_count: 20000, status: 'active', created_at: '', updated_at: '', }); updateCycleMock.mockResolvedValue({ id: 22, kandang: 11, total_days: 40, current_day: 1, start_date: '2026-08-01', end_date: '2026-09-09', chick_in_weight: 38, doc_in_count: 18000, status: 'closed', created_at: '', updated_at: '', }); }); it('submits only backend-supported kandang fields', async () => { render(); fireEvent.change(screen.getByPlaceholderText('Nama kandang'), { target: { value: 'Kandang 1' }, }); fireEvent.click(screen.getByRole('button', { name: 'Tambah kandang' })); await waitFor(() => expect(createKandangMock).toHaveBeenCalledTimes(1)); expect(createKandangMock).toHaveBeenCalledWith({ kandang_name: 'Kandang 1', site: 7, }); }); it('submits flock fields for the selected kandang', async () => { farmState.kandangs = [ { id: 11, kandang_name: 'Kandang 1', site: 7, created_at: '', updated_at: '' }, ]; farmState.selectedKandangId = 11; render(); fireEvent.change(screen.getByPlaceholderText('Nama flock'), { target: { value: 'Lantai 1' }, }); fireEvent.click(screen.getByRole('button', { name: 'Tambah flock' })); await waitFor(() => expect(createFlockMock).toHaveBeenCalledTimes(1)); expect(createFlockMock).toHaveBeenCalledWith({ flock_name: 'Lantai 1', kandang: 11, }); }); it('submits cycle fields without flock assignment', async () => { farmState.kandangs = [ { id: 11, kandang_name: 'Kandang 1', site: 7, created_at: '', updated_at: '' }, ]; farmState.selectedKandangId = 11; render(); expect(screen.queryByLabelText(/^Siklus$/i)).not.toBeInTheDocument(); expect(screen.queryByLabelText(/Total hari/i)).not.toBeInTheDocument(); fireEvent.change(screen.getByLabelText(/Mulai/i), { target: { value: '2026-08-01' } }); fireEvent.change(screen.getByLabelText(/Selesai/i), { target: { value: '2026-09-04' } }); fireEvent.click(screen.getByRole('button', { name: 'Tambah siklus' })); await waitFor(() => expect(createCycleMock).toHaveBeenCalledTimes(1)); expect(createCycleMock).toHaveBeenCalledWith({ kandang: 11, total_days: 35, current_day: 1, start_date: '2026-08-01', end_date: '2026-09-04', chick_in_weight: 35, doc_in_count: 20000, }); }); it('updates an existing cycle from the edit form', async () => { farmState.kandangs = [ { id: 11, kandang_name: 'Kandang 1', site: 7, created_at: '', updated_at: '' }, ]; farmState.selectedKandangId = 11; farmState.cycles = [ { id: 22, kandang: 11, kandang_name: 'Kandang 1', total_days: 35, current_day: 1, visible_through_date: '2026-08-18', start_date: '2026-08-01', end_date: '2026-09-04', chick_in_weight: 35, doc_in_count: 20000, feed_initial_balance: 0, status: 'active', created_at: '', updated_at: '', }, ]; render(); fireEvent.click(screen.getByRole('button', { name: 'Ubah' })); fireEvent.change(screen.getByLabelText(/DOC in/i), { target: { value: '18000' } }); fireEvent.change(screen.getByLabelText(/Berat DOC/i), { target: { value: '38' } }); fireEvent.click(screen.getByRole('button', { name: 'Simpan perubahan' })); await waitFor(() => expect(updateCycleMock).toHaveBeenCalledTimes(1)); expect(updateCycleMock).toHaveBeenCalledWith(22, { kandang: 11, total_days: 35, start_date: '2026-08-01', end_date: '2026-09-04', chick_in_weight: 38, doc_in_count: 18000, }); }); });