116 lines
4.2 KiB
TypeScript
116 lines
4.2 KiB
TypeScript
// @vitest-environment jsdom
|
|
import { beforeEach, describe, expect, it, vi } from 'vitest';
|
|
import { render, screen, waitFor } from '@testing-library/react';
|
|
import userEvent from '@testing-library/user-event';
|
|
import { ConfigTab } from './ConfigTab';
|
|
|
|
const {
|
|
authState,
|
|
fetchDynamicConfigItemsMock,
|
|
upsertDynamicConfigItemsMock
|
|
} = vi.hoisted(() => ({
|
|
authState: {
|
|
profile: { role: 'admin' } as any
|
|
},
|
|
fetchDynamicConfigItemsMock: vi.fn(),
|
|
upsertDynamicConfigItemsMock: vi.fn()
|
|
}));
|
|
|
|
vi.mock('../components/AuthContext', () => ({
|
|
useAuth: () => authState
|
|
}));
|
|
|
|
vi.mock('../lib/dynamicConfigApi', () => ({
|
|
fetchDynamicConfigItems: fetchDynamicConfigItemsMock,
|
|
upsertDynamicConfigItems: upsertDynamicConfigItemsMock
|
|
}));
|
|
|
|
describe('ConfigTab DOM behavior', () => {
|
|
beforeEach(() => {
|
|
authState.profile.role = 'admin';
|
|
fetchDynamicConfigItemsMock.mockReset();
|
|
upsertDynamicConfigItemsMock.mockReset();
|
|
fetchDynamicConfigItemsMock.mockResolvedValue([
|
|
{ key: 'BOT_MODE', value: 'enabled', description: 'Bot mode' },
|
|
{ key: 'API_KEY', value: 'masked', description: 'Secret key' }
|
|
]);
|
|
upsertDynamicConfigItemsMock.mockResolvedValue(undefined);
|
|
});
|
|
|
|
it('loads configs, supports edit/reset, and saves with success message', async () => {
|
|
const user = userEvent.setup();
|
|
render(<ConfigTab />);
|
|
|
|
await waitFor(() => {
|
|
expect(screen.getByDisplayValue('enabled')).toBeInTheDocument();
|
|
expect(screen.getByRole('button', { name: 'Commit Changes' })).toBeDisabled();
|
|
});
|
|
|
|
const modeTextarea = screen.getByDisplayValue('enabled');
|
|
await user.clear(modeTextarea);
|
|
await user.type(modeTextarea, 'disabled');
|
|
|
|
expect(screen.getByRole('button', { name: 'Commit Changes' })).toBeEnabled();
|
|
expect(screen.getByRole('button', { name: 'Abort Changes' })).toBeInTheDocument();
|
|
|
|
await user.click(screen.getByRole('button', { name: 'Abort Changes' }));
|
|
expect(screen.getByDisplayValue('enabled')).toBeInTheDocument();
|
|
|
|
const resetModeTextarea = screen.getByDisplayValue('enabled');
|
|
await user.clear(resetModeTextarea);
|
|
await user.type(resetModeTextarea, 'disabled');
|
|
await user.click(screen.getByRole('button', { name: 'Commit Changes' }));
|
|
|
|
await waitFor(() => {
|
|
expect(upsertDynamicConfigItemsMock).toHaveBeenCalledTimes(1);
|
|
expect(screen.getByText('SYNC COMPLETE')).toBeInTheDocument();
|
|
});
|
|
|
|
expect(upsertDynamicConfigItemsMock.mock.calls[0][0]).toEqual(
|
|
expect.arrayContaining([
|
|
expect.objectContaining({ key: 'BOT_MODE', value: 'disabled' }),
|
|
expect.objectContaining({ key: 'API_KEY', value: 'masked' })
|
|
])
|
|
);
|
|
}, 20000);
|
|
|
|
it('renders empty-state table when no config rows exist', async () => {
|
|
fetchDynamicConfigItemsMock.mockResolvedValueOnce([]);
|
|
render(<ConfigTab />);
|
|
|
|
await waitFor(() => {
|
|
expect(screen.getByText('Configuration Map Null')).toBeInTheDocument();
|
|
});
|
|
});
|
|
|
|
it('shows save error banner when upsert fails', async () => {
|
|
upsertDynamicConfigItemsMock.mockRejectedValueOnce(new Error('write failed'));
|
|
const user = userEvent.setup();
|
|
|
|
render(<ConfigTab />);
|
|
|
|
await waitFor(() => {
|
|
expect(screen.getByDisplayValue('enabled')).toBeInTheDocument();
|
|
});
|
|
|
|
const modeTextarea = screen.getByDisplayValue('enabled');
|
|
await user.clear(modeTextarea);
|
|
await user.type(modeTextarea, 'paused');
|
|
await user.click(screen.getByRole('button', { name: 'Commit Changes' }));
|
|
|
|
await waitFor(() => {
|
|
expect(screen.getByText('CRITICAL ERROR')).toBeInTheDocument();
|
|
expect(screen.getByText(/Sync failed: write failed/)).toBeInTheDocument();
|
|
});
|
|
}, 20000);
|
|
|
|
it('denies access to non-admin users without fetching dynamic config', () => {
|
|
authState.profile.role = 'user';
|
|
|
|
render(<ConfigTab />);
|
|
|
|
expect(screen.getByText(/Access Denied/i)).toBeInTheDocument();
|
|
expect(fetchDynamicConfigItemsMock).not.toHaveBeenCalled();
|
|
});
|
|
});
|