Initial commit: Brachnha Insight project setup
- Next.js 14+ with App Router and TypeScript - Tailwind CSS and ShadCN UI styling - Zustand state management - Dexie.js for IndexedDB (local-first data) - Auth.js v5 for authentication - BMAD framework integration Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
132
src/components/features/settings/provider-form.test.tsx
Normal file
132
src/components/features/settings/provider-form.test.tsx
Normal file
@@ -0,0 +1,132 @@
|
||||
import { describe, it, expect, beforeEach, vi } from 'vitest';
|
||||
import { render, screen, fireEvent } from '@testing-library/react';
|
||||
import { ProviderForm } from './provider-form';
|
||||
import { useSettingsStore } from '@/store/use-settings';
|
||||
|
||||
// Mock ConnectionStatus component
|
||||
vi.mock('./connection-status', () => ({
|
||||
ConnectionStatus: () => <div data-testid="connection-status">Connection Status</div>,
|
||||
}));
|
||||
|
||||
describe('ProviderForm', () => {
|
||||
beforeEach(() => {
|
||||
// Reset store state
|
||||
useSettingsStore.setState({
|
||||
apiKey: '',
|
||||
baseUrl: 'https://api.openai.com/v1',
|
||||
modelName: 'gpt-4-turbo-preview',
|
||||
isConfigured: false,
|
||||
});
|
||||
});
|
||||
|
||||
it('renders all required input fields', () => {
|
||||
render(<ProviderForm />);
|
||||
|
||||
expect(screen.getByLabelText(/base url/i)).toBeInTheDocument();
|
||||
expect(screen.getByLabelText(/model name/i)).toBeInTheDocument();
|
||||
// Use placeholder for API key since show/hide button has "API key" in aria-label
|
||||
expect(screen.getByPlaceholderText('sk-...')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('shows helper text for API key', () => {
|
||||
render(<ProviderForm />);
|
||||
|
||||
expect(screen.getByText(/stored locally in your browser with basic encoding/i)).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('has show/hide toggle for API key', () => {
|
||||
render(<ProviderForm />);
|
||||
|
||||
const apiKeyInput = screen.getByPlaceholderText('sk-...') as HTMLInputElement;
|
||||
const toggleButton = screen.getByRole('button', { name: /show/i });
|
||||
|
||||
// Initially password type
|
||||
expect(apiKeyInput.type).toBe('password');
|
||||
|
||||
// Click show button
|
||||
fireEvent.click(toggleButton);
|
||||
|
||||
// Should change to text type
|
||||
expect(apiKeyInput.type).toBe('text');
|
||||
});
|
||||
|
||||
it('updates base URL when user types', () => {
|
||||
render(<ProviderForm />);
|
||||
|
||||
const baseUrlInput = screen.getByLabelText(/base url/i);
|
||||
fireEvent.change(baseUrlInput, { target: { value: 'https://api.deepseek.com/v1' } });
|
||||
|
||||
const state = useSettingsStore.getState();
|
||||
expect(state.baseUrl).toBe('https://api.deepseek.com/v1');
|
||||
});
|
||||
|
||||
it('updates model name when user types', () => {
|
||||
render(<ProviderForm />);
|
||||
|
||||
const modelInput = screen.getByLabelText(/model name/i);
|
||||
fireEvent.change(modelInput, { target: { value: 'deepseek-chat' } });
|
||||
|
||||
const state = useSettingsStore.getState();
|
||||
expect(state.modelName).toBe('deepseek-chat');
|
||||
});
|
||||
|
||||
it('updates API key when user types', () => {
|
||||
render(<ProviderForm />);
|
||||
|
||||
const apiKeyInput = screen.getByPlaceholderText('sk-...');
|
||||
fireEvent.change(apiKeyInput, { target: { value: 'sk-test-key-12345' } });
|
||||
|
||||
const state = useSettingsStore.getState();
|
||||
expect(state.apiKey).toBe('sk-test-key-12345');
|
||||
expect(state.isConfigured).toBe(true);
|
||||
});
|
||||
|
||||
it('displays current values from store', () => {
|
||||
useSettingsStore.setState({
|
||||
apiKey: 'sk-existing-key',
|
||||
baseUrl: 'https://api.custom.com/v1',
|
||||
modelName: 'custom-model',
|
||||
isConfigured: true,
|
||||
});
|
||||
|
||||
render(<ProviderForm />);
|
||||
|
||||
expect(screen.getByPlaceholderText('sk-...')).toHaveValue('sk-existing-key');
|
||||
expect(screen.getByLabelText(/base url/i)).toHaveValue('https://api.custom.com/v1');
|
||||
expect(screen.getByLabelText(/model name/i)).toHaveValue('custom-model');
|
||||
});
|
||||
|
||||
it('renders ConnectionStatus component', () => {
|
||||
render(<ProviderForm />);
|
||||
|
||||
expect(screen.getByTestId('connection-status')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('has proper accessibility attributes', () => {
|
||||
render(<ProviderForm />);
|
||||
|
||||
// All inputs should have associated labels
|
||||
expect(screen.getByLabelText(/base url/i)).toBeInTheDocument();
|
||||
expect(screen.getByLabelText(/model name/i)).toBeInTheDocument();
|
||||
expect(screen.getByPlaceholderText('sk-...')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('displays provider preset buttons', () => {
|
||||
render(<ProviderForm />);
|
||||
|
||||
expect(screen.getByRole('button', { name: 'OpenAI' })).toBeInTheDocument();
|
||||
expect(screen.getByRole('button', { name: 'DeepSeek' })).toBeInTheDocument();
|
||||
expect(screen.getByRole('button', { name: 'OpenRouter' })).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('applies preset when clicked', () => {
|
||||
render(<ProviderForm />);
|
||||
|
||||
const deepseekButton = screen.getByRole('button', { name: 'DeepSeek' });
|
||||
fireEvent.click(deepseekButton);
|
||||
|
||||
const state = useSettingsStore.getState();
|
||||
expect(state.baseUrl).toBe('https://api.deepseek.com/v1');
|
||||
expect(state.modelName).toBe('deepseek-chat');
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user