Files
dashboard-cpsp-executive/components/__tests__/UserManagementPage.test.tsx
T

151 lines
4.3 KiB
TypeScript

import { fireEvent, render, screen, waitFor } from '@testing-library/react';
import { beforeEach, describe, expect, it, vi } from 'vitest';
import UserManagementPage from '../UserManagementPage.tsx';
const { listMock, createMock, updateMock, setPasswordMock, authState } = vi.hoisted(() => ({
listMock: vi.fn(),
createMock: vi.fn(),
updateMock: vi.fn(),
setPasswordMock: vi.fn(),
authState: {
user: {
id: 99,
user_name: 'account_admin',
display_name: 'account_admin',
status: 'account_admin' as string,
created_at: '',
updated_at: '',
},
},
}));
vi.mock('../../services/apiClient.ts', () => ({
api: {
users: {
list: listMock,
create: createMock,
update: updateMock,
setPassword: setPasswordMock,
},
},
errorMessage: (err: unknown) => (err instanceof Error ? err.message : 'Terjadi kesalahan'),
}));
vi.mock('../../context/AuthContext.tsx', () => ({
useAuth: () => ({
user: authState.user,
}),
}));
describe('UserManagementPage', () => {
beforeEach(() => {
listMock.mockReset();
createMock.mockReset();
updateMock.mockReset();
setPasswordMock.mockReset();
authState.user = {
id: 99,
user_name: 'account_admin',
display_name: 'account_admin',
status: 'account_admin',
created_at: '',
updated_at: '',
};
listMock.mockResolvedValue([
{
id: 1,
user_name: 'gm1.login',
display_name: 'gm1',
status: 'gm',
managed_by_name: 'buh1',
created_at: '',
updated_at: '',
},
{
id: 99,
user_name: 'account_admin',
display_name: 'account_admin',
status: 'account_admin',
managed_by_name: null,
created_at: '',
updated_at: '',
},
]);
createMock.mockResolvedValue({
id: 2,
user_name: 'newgm',
display_name: 'newgm',
status: 'gm',
created_at: '',
updated_at: '',
});
updateMock.mockResolvedValue({});
setPasswordMock.mockResolvedValue({});
vi.spyOn(window, 'confirm').mockReturnValue(true);
});
it('renders list from api.users.list', async () => {
render(<UserManagementPage />);
expect(await screen.findByText('gm1')).toBeInTheDocument();
expect(screen.getByText('buh1')).toBeInTheDocument();
expect(screen.getAllByText('GM').length).toBeGreaterThan(0);
});
it('submits create with password', async () => {
render(<UserManagementPage />);
await screen.findByText('gm1');
fireEvent.change(screen.getByLabelText(/^Login$/i), {
target: { value: 'newgm' },
});
fireEvent.change(screen.getByLabelText(/^Nama$/i), {
target: { value: 'New GM' },
});
fireEvent.change(screen.getByLabelText(/Password sementara/i), {
target: { value: 'temp123' },
});
fireEvent.click(screen.getByRole('button', { name: /Buat akun/i }));
await waitFor(() => {
expect(createMock).toHaveBeenCalledWith({
user_name: 'newgm',
display_name: 'New GM',
status: 'gm',
password: 'temp123',
});
});
});
it('deactivates user', async () => {
render(<UserManagementPage />);
await screen.findByText('gm1');
fireEvent.click(screen.getByRole('button', { name: /Nonaktifkan/i }));
await waitFor(() => {
expect(updateMock).toHaveBeenCalledWith(1, { status: 'inactive' });
});
});
it('hides deactivate and role change on own row', async () => {
render(<UserManagementPage />);
expect(await screen.findByText('(Anda)')).toBeInTheDocument();
expect(screen.getAllByRole('button', { name: /Nonaktifkan/i })).toHaveLength(1);
expect(screen.getAllByRole('button', { name: /Ubah role/i })).toHaveLength(1);
expect(
screen.getByText(/Role & status akun sendiri tidak bisa diubah/i)
).toBeInTheDocument();
});
it('resets password', async () => {
render(<UserManagementPage />);
await screen.findByText('gm1');
fireEvent.click(screen.getAllByRole('button', { name: /Reset password/i })[0]);
fireEvent.change(screen.getByPlaceholderText(/Password baru/i), {
target: { value: 'reset-me' },
});
fireEvent.click(screen.getByRole('button', { name: /^Reset$/i }));
await waitFor(() => {
expect(setPasswordMock).toHaveBeenCalledWith(1, 'reset-me');
});
});
});