update api export for executive and fixing closing cycle flow
This commit is contained in:
1 parent
d0d1ae7d24
commit
07d36081ce
23 files changed
+1378
-101
No files matched your search
@@ -0,0 +1,119 @@
|
||||
import { fireEvent, render, screen, waitFor } from '@testing-library/react';
|
||||
import { beforeEach, describe, expect, it, vi } from 'vitest';
|
||||
import DashboardCloseCycleControls from '../DashboardCloseCycleControls.tsx';
|
||||
|
||||
const {
|
||||
requestCloseMock,
|
||||
cancelCloseRequestMock,
|
||||
reloadMock,
|
||||
farmState,
|
||||
authState,
|
||||
} = vi.hoisted(() => ({
|
||||
requestCloseMock: vi.fn().mockResolvedValue({}),
|
||||
cancelCloseRequestMock: vi.fn().mockResolvedValue({}),
|
||||
reloadMock: vi.fn().mockResolvedValue(undefined),
|
||||
farmState: {
|
||||
selectedCycle: {
|
||||
id: 5,
|
||||
start_date: '2026-09-01',
|
||||
end_date: null,
|
||||
status: 'active',
|
||||
proposed_end_date: null,
|
||||
visible_through_date: '2026-09-10',
|
||||
} as Record<string, unknown> | null,
|
||||
},
|
||||
authState: {
|
||||
user: {
|
||||
id: 1,
|
||||
user_name: 'staff',
|
||||
display_name: 'Staff',
|
||||
status: 'active',
|
||||
},
|
||||
},
|
||||
}));
|
||||
|
||||
vi.mock('../../../services/apiClient.ts', () => ({
|
||||
api: {
|
||||
cycles: {
|
||||
requestClose: requestCloseMock,
|
||||
cancelCloseRequest: cancelCloseRequestMock,
|
||||
},
|
||||
},
|
||||
errorMessage: (err: unknown) => (err instanceof Error ? err.message : 'Terjadi kesalahan'),
|
||||
}));
|
||||
|
||||
vi.mock('../../../context/AuthContext.tsx', () => ({
|
||||
useAuth: () => authState,
|
||||
}));
|
||||
|
||||
vi.mock('../../../context/FarmContext.tsx', () => ({
|
||||
useFarm: () => ({
|
||||
selectedCycle: farmState.selectedCycle,
|
||||
reload: reloadMock,
|
||||
}),
|
||||
}));
|
||||
|
||||
describe('DashboardCloseCycleControls', () => {
|
||||
beforeEach(() => {
|
||||
requestCloseMock.mockClear();
|
||||
cancelCloseRequestMock.mockClear();
|
||||
reloadMock.mockClear();
|
||||
authState.user.status = 'active';
|
||||
farmState.selectedCycle = {
|
||||
id: 5,
|
||||
start_date: '2026-09-01',
|
||||
end_date: null,
|
||||
status: 'active',
|
||||
proposed_end_date: null,
|
||||
visible_through_date: '2026-09-10',
|
||||
};
|
||||
});
|
||||
|
||||
it('shows date + Ajukan tutup for active cycle and requires confirm before API', async () => {
|
||||
render(<DashboardCloseCycleControls />);
|
||||
expect(screen.getByRole('button', { name: /Ajukan tutup/i })).toBeInTheDocument();
|
||||
fireEvent.click(screen.getByRole('button', { name: /Ajukan tutup/i }));
|
||||
expect(requestCloseMock).not.toHaveBeenCalled();
|
||||
expect(screen.getByRole('dialog')).toBeInTheDocument();
|
||||
fireEvent.click(screen.getByRole('button', { name: /Ya, ajukan tutup/i }));
|
||||
await waitFor(() => {
|
||||
expect(requestCloseMock).toHaveBeenCalledWith(5, {
|
||||
proposed_end_date: expect.any(String),
|
||||
});
|
||||
});
|
||||
expect(reloadMock).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('shows cancel control when pending_close', () => {
|
||||
farmState.selectedCycle = {
|
||||
id: 5,
|
||||
start_date: '2026-09-01',
|
||||
end_date: null,
|
||||
status: 'pending_close',
|
||||
proposed_end_date: '2026-09-15',
|
||||
visible_through_date: '2026-09-10',
|
||||
};
|
||||
render(<DashboardCloseCycleControls />);
|
||||
expect(screen.queryByRole('button', { name: /Ajukan tutup/i })).not.toBeInTheDocument();
|
||||
expect(screen.getByRole('button', { name: /Batalkan permintaan/i })).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('hides controls for non-active users', () => {
|
||||
authState.user.status = 'superadmin';
|
||||
render(<DashboardCloseCycleControls />);
|
||||
expect(screen.queryByRole('button', { name: /Ajukan tutup/i })).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('shows API failure in an alert popup', async () => {
|
||||
requestCloseMock.mockRejectedValueOnce(
|
||||
new Error('gagal kirim ke pusat — coba lagi (400: {"detail":"Cycle is already closed."})')
|
||||
);
|
||||
render(<DashboardCloseCycleControls />);
|
||||
fireEvent.click(screen.getByRole('button', { name: /Ajukan tutup/i }));
|
||||
fireEvent.click(screen.getByRole('button', { name: /Ya, ajukan tutup/i }));
|
||||
expect(await screen.findByRole('alertdialog')).toBeInTheDocument();
|
||||
expect(screen.getByText(/Cycle is already closed/i)).toBeInTheDocument();
|
||||
fireEvent.click(screen.getByRole('button', { name: /^Tutup$/i }));
|
||||
expect(screen.queryByRole('alertdialog')).not.toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
Reference in new issue
Block a user