Files
lcbp3/frontend/components/admin/reference/__tests__/generic-crud-table.test.tsx
T
admin 7e8f4859cd
CI / CD Pipeline / build (push) Failing after 6m24s
CI / CD Pipeline / deploy (push) Has been skipped
feat(ai): add ADR-036 unified OCR architecture and frontend test coverage
- Add ADR-036 unified OCR architecture (typhoon-ocr via Ollama)
- Extend AI execution profiles for OCR sandbox configuration
- Add comprehensive frontend test coverage (components, hooks, services)
- Add backend test coverage for document-numbering services
- Update OCR sidecar with typhoon-ocr integration
- Add AI policy service and execution profile management
- Update AGENTS.md and architecture documentation
2026-06-14 06:34:07 +07:00

95 lines
3.2 KiB
TypeScript

// File: frontend/components/admin/reference/__tests__/generic-crud-table.test.tsx
// Change Log
// - 2026-06-13: Add coverage for generic reference CRUD table states and create mutation.
import { render, screen, waitFor } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { type ColumnDef } from '@tanstack/react-table';
import { beforeEach, describe, expect, it, vi } from 'vitest';
import { toast } from 'sonner';
import { createTestQueryClient } from '@/lib/test-utils';
import { GenericCrudTable } from '../generic-crud-table';
type ReferenceRow = {
id: number;
publicId: string;
code: string;
name: string;
active: boolean;
};
const rows: ReferenceRow[] = [
{
id: 1,
publicId: '019505a1-7c3e-7000-8000-abc123def701',
code: 'DISC',
name: 'Discipline',
active: true,
},
];
const columns: ColumnDef<ReferenceRow>[] = [
{ accessorKey: 'code', header: 'Code' },
{ accessorKey: 'name', header: 'Name' },
];
function renderTable(overrides?: Partial<React.ComponentProps<typeof GenericCrudTable<ReferenceRow>>>) {
const { wrapper } = createTestQueryClient();
const props: React.ComponentProps<typeof GenericCrudTable<ReferenceRow>> = {
title: 'Reference Data',
description: 'Manage reference data',
entityName: 'Reference',
queryKey: ['reference-test'],
fetchFn: vi.fn().mockResolvedValue(rows),
createFn: vi.fn().mockResolvedValue({ success: true }),
updateFn: vi.fn().mockResolvedValue({ success: true }),
deleteFn: vi.fn().mockResolvedValue({ success: true }),
columns,
fields: [
{ name: 'code', label: 'Code', type: 'text', required: true },
{ name: 'name', label: 'Name', type: 'textarea' },
{ name: 'active', label: 'Active', type: 'checkbox' },
],
...overrides,
};
return {
...render(<GenericCrudTable<ReferenceRow> {...props} />, { wrapper }),
props,
};
}
describe('GenericCrudTable', () => {
beforeEach(() => {
vi.clearAllMocks();
});
it('renders data rows returned by fetchFn', async () => {
renderTable();
expect(await screen.findByText('DISC')).toBeInTheDocument();
expect(screen.getByText('Reference Data')).toBeInTheDocument();
expect(screen.getByText('Discipline')).toBeInTheDocument();
});
it('renders empty state for wrapped empty data', async () => {
renderTable({ fetchFn: vi.fn().mockResolvedValue({ data: [] }) });
expect(await screen.findByText('No data found.')).toBeInTheDocument();
});
it('creates a new item from dialog form', async () => {
const user = userEvent.setup();
const createFn = vi.fn().mockResolvedValue({ success: true });
renderTable({ createFn });
await user.click(await screen.findByRole('button', { name: /add reference/i }));
await user.type(screen.getByLabelText(/code/i), 'AREA');
await user.type(screen.getByLabelText(/name/i), 'Area');
await user.click(screen.getByRole('button', { name: /^add reference$/i }));
await waitFor(() => {
expect(createFn).toHaveBeenCalledWith(
expect.objectContaining({ code: 'AREA', name: 'Area', active: true }),
expect.any(Object)
);
});
expect(toast.success).toHaveBeenCalledWith('Reference created successfully');
});
});