// @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(); 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(); 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(); 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(); expect(screen.getByText(/Access Denied/i)).toBeInTheDocument(); expect(fetchDynamicConfigItemsMock).not.toHaveBeenCalled(); }); });