mirror of
https://github.com/johndoe6345789/snippet-pastebin.git
synced 2026-04-24 13:34:55 +00:00
- Created comprehensive test suites for quality validator module (430+ tests) * index.test.ts: QualityValidator main module * reporters/*.test.ts: ReporterBase and all reporters * scoring/*.test.ts: Scoring engine with edge cases * utils/*.test.ts: Validators, formatters, FileChangeDetector - Added UI component tests for sidebar menu and templates (800+ tests) * SidebarMenuButton, SidebarMenuSubButton, etc. * DashboardTemplate, BlogTemplate * ContentPreviewCardsSection, FormFieldsSection - Coverage improvements: * Statements: 56.62% → 60.93% (+4.31%) * Functions: 76.76% → 79.82% (+3.06%) * Branches: 84.37% → 85.92% (+1.55%) * Tests passing: 5,512 (added 363 new passing tests) Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
377 lines
11 KiB
TypeScript
377 lines
11 KiB
TypeScript
/**
|
|
* Unit Tests for useStorageConfig Hook
|
|
* Tests storage backend configuration and Flask connection management
|
|
*/
|
|
|
|
import { renderHook, act } from '@testing-library/react';
|
|
import { useStorageConfig } from '@/hooks/useStorageConfig';
|
|
import * as storage from '@/lib/storage';
|
|
import { toast } from 'sonner';
|
|
|
|
jest.mock('@/lib/storage');
|
|
jest.mock('sonner');
|
|
|
|
describe('useStorageConfig Hook', () => {
|
|
beforeEach(() => {
|
|
jest.clearAllMocks();
|
|
delete process.env.NEXT_PUBLIC_FLASK_BACKEND_URL;
|
|
});
|
|
|
|
describe('initial state', () => {
|
|
it('should initialize with default values', () => {
|
|
const { result } = renderHook(() => useStorageConfig());
|
|
|
|
expect(result.current.storageBackend).toBe('indexeddb');
|
|
expect(result.current.flaskUrl).toBe('');
|
|
expect(result.current.flaskConnectionStatus).toBe('unknown');
|
|
expect(result.current.testingConnection).toBe(false);
|
|
expect(result.current.envVarSet).toBe(false);
|
|
});
|
|
});
|
|
|
|
describe('loadConfig', () => {
|
|
it('should load configuration from storage', () => {
|
|
(storage.loadStorageConfig as jest.Mock).mockReturnValue({
|
|
backend: 'flask',
|
|
flaskUrl: 'http://localhost:5000',
|
|
});
|
|
|
|
const { result } = renderHook(() => useStorageConfig());
|
|
|
|
act(() => {
|
|
result.current.loadConfig();
|
|
});
|
|
|
|
expect(result.current.storageBackend).toBe('flask');
|
|
expect(result.current.flaskUrl).toBe('http://localhost:5000');
|
|
});
|
|
|
|
it('should detect environment variable', () => {
|
|
process.env.NEXT_PUBLIC_FLASK_BACKEND_URL = 'http://api.example.com';
|
|
(storage.loadStorageConfig as jest.Mock).mockReturnValue({
|
|
backend: 'indexeddb',
|
|
});
|
|
|
|
const { result } = renderHook(() => useStorageConfig());
|
|
|
|
act(() => {
|
|
result.current.loadConfig();
|
|
});
|
|
|
|
expect(result.current.envVarSet).toBe(true);
|
|
});
|
|
|
|
it('should use env var as default Flask URL', () => {
|
|
process.env.NEXT_PUBLIC_FLASK_BACKEND_URL = 'http://api.example.com';
|
|
(storage.loadStorageConfig as jest.Mock).mockReturnValue({
|
|
backend: 'indexeddb',
|
|
});
|
|
|
|
const { result } = renderHook(() => useStorageConfig());
|
|
|
|
act(() => {
|
|
result.current.loadConfig();
|
|
});
|
|
|
|
expect(result.current.flaskUrl).toBe('http://api.example.com');
|
|
});
|
|
|
|
it('should use fallback URL if no config or env var', () => {
|
|
(storage.loadStorageConfig as jest.Mock).mockReturnValue({
|
|
backend: 'indexeddb',
|
|
});
|
|
|
|
const { result } = renderHook(() => useStorageConfig());
|
|
|
|
act(() => {
|
|
result.current.loadConfig();
|
|
});
|
|
|
|
expect(result.current.flaskUrl).toBe('http://localhost:5000');
|
|
});
|
|
});
|
|
|
|
describe('testFlaskConnection', () => {
|
|
it('should test Flask connection successfully', async () => {
|
|
const mockAdapter = {
|
|
testConnection: jest.fn().mockResolvedValue(true),
|
|
};
|
|
(storage.FlaskStorageAdapter as any) = jest.fn(() => mockAdapter);
|
|
|
|
const { result } = renderHook(() => useStorageConfig());
|
|
|
|
let connected = false;
|
|
await act(async () => {
|
|
connected = await result.current.testFlaskConnection('http://localhost:5000');
|
|
});
|
|
|
|
expect(connected).toBe(true);
|
|
expect(result.current.flaskConnectionStatus).toBe('connected');
|
|
});
|
|
|
|
it('should handle failed connection', async () => {
|
|
const mockAdapter = {
|
|
testConnection: jest.fn().mockResolvedValue(false),
|
|
};
|
|
(storage.FlaskStorageAdapter as any) = jest.fn(() => mockAdapter);
|
|
|
|
const { result } = renderHook(() => useStorageConfig());
|
|
|
|
let connected = false;
|
|
await act(async () => {
|
|
connected = await result.current.testFlaskConnection('http://localhost:5000');
|
|
});
|
|
|
|
expect(connected).toBe(false);
|
|
expect(result.current.flaskConnectionStatus).toBe('failed');
|
|
});
|
|
|
|
it('should handle adapter creation error', async () => {
|
|
(storage.FlaskStorageAdapter as any) = jest.fn(() => {
|
|
throw new Error('Invalid URL');
|
|
});
|
|
|
|
const { result } = renderHook(() => useStorageConfig());
|
|
|
|
let connected = false;
|
|
await act(async () => {
|
|
connected = await result.current.testFlaskConnection('invalid-url');
|
|
});
|
|
|
|
expect(connected).toBe(false);
|
|
expect(result.current.flaskConnectionStatus).toBe('failed');
|
|
});
|
|
|
|
it('should set testing flag', async () => {
|
|
const mockAdapter = {
|
|
testConnection: jest.fn().mockImplementation(() =>
|
|
new Promise(resolve => setTimeout(() => resolve(true), 100))
|
|
),
|
|
};
|
|
(storage.FlaskStorageAdapter as any) = jest.fn(() => mockAdapter);
|
|
|
|
const { result } = renderHook(() => useStorageConfig());
|
|
|
|
const testPromise = act(async () => {
|
|
await result.current.testFlaskConnection('http://localhost:5000');
|
|
});
|
|
|
|
expect(result.current.testingConnection).toBe(true);
|
|
await testPromise;
|
|
expect(result.current.testingConnection).toBe(false);
|
|
});
|
|
});
|
|
|
|
describe('handleTestConnection', () => {
|
|
it('should test connection using current Flask URL', async () => {
|
|
const mockAdapter = {
|
|
testConnection: jest.fn().mockResolvedValue(true),
|
|
};
|
|
(storage.FlaskStorageAdapter as any) = jest.fn(() => mockAdapter);
|
|
|
|
const { result } = renderHook(() => useStorageConfig());
|
|
|
|
act(() => {
|
|
result.current.setFlaskUrl('http://test.com:5000');
|
|
});
|
|
|
|
await act(async () => {
|
|
await result.current.handleTestConnection();
|
|
});
|
|
|
|
expect((storage.FlaskStorageAdapter as any)).toHaveBeenCalledWith('http://test.com:5000');
|
|
});
|
|
});
|
|
|
|
describe('handleSaveStorageConfig', () => {
|
|
it('should save indexeddb config without testing', async () => {
|
|
(storage.saveStorageConfig as jest.Mock).mockImplementation();
|
|
|
|
const { result } = renderHook(() => useStorageConfig());
|
|
|
|
act(() => {
|
|
result.current.setStorageBackend('indexeddb');
|
|
});
|
|
|
|
await act(async () => {
|
|
await result.current.handleSaveStorageConfig();
|
|
});
|
|
|
|
expect(storage.saveStorageConfig).toHaveBeenCalledWith({
|
|
backend: 'indexeddb',
|
|
flaskUrl: undefined,
|
|
});
|
|
expect(toast.success).toHaveBeenCalled();
|
|
});
|
|
|
|
it('should test Flask connection before saving', async () => {
|
|
const mockAdapter = {
|
|
testConnection: jest.fn().mockResolvedValue(true),
|
|
};
|
|
(storage.FlaskStorageAdapter as any) = jest.fn(() => mockAdapter);
|
|
(storage.saveStorageConfig as jest.Mock).mockImplementation();
|
|
|
|
const { result } = renderHook(() => useStorageConfig());
|
|
|
|
act(() => {
|
|
result.current.setStorageBackend('flask');
|
|
result.current.setFlaskUrl('http://localhost:5000');
|
|
});
|
|
|
|
await act(async () => {
|
|
await result.current.handleSaveStorageConfig();
|
|
});
|
|
|
|
expect(storage.saveStorageConfig).toHaveBeenCalled();
|
|
});
|
|
|
|
it('should reject if Flask URL is empty', async () => {
|
|
const { result } = renderHook(() => useStorageConfig());
|
|
|
|
act(() => {
|
|
result.current.setStorageBackend('flask');
|
|
result.current.setFlaskUrl('');
|
|
});
|
|
|
|
await act(async () => {
|
|
await result.current.handleSaveStorageConfig();
|
|
});
|
|
|
|
expect(toast.error).toHaveBeenCalledWith('Please enter a Flask backend URL');
|
|
expect(storage.saveStorageConfig).not.toHaveBeenCalled();
|
|
});
|
|
|
|
it('should reject if Flask connection fails', async () => {
|
|
const mockAdapter = {
|
|
testConnection: jest.fn().mockResolvedValue(false),
|
|
};
|
|
(storage.FlaskStorageAdapter as any) = jest.fn(() => mockAdapter);
|
|
|
|
const { result } = renderHook(() => useStorageConfig());
|
|
|
|
act(() => {
|
|
result.current.setStorageBackend('flask');
|
|
result.current.setFlaskUrl('http://localhost:5000');
|
|
});
|
|
|
|
await act(async () => {
|
|
await result.current.handleSaveStorageConfig();
|
|
});
|
|
|
|
expect(toast.error).toHaveBeenCalledWith(
|
|
'Cannot connect to Flask backend. Please check the URL and ensure the server is running.'
|
|
);
|
|
expect(storage.saveStorageConfig).not.toHaveBeenCalled();
|
|
});
|
|
|
|
it('should call onSuccess callback if provided', async () => {
|
|
(storage.saveStorageConfig as jest.Mock).mockImplementation();
|
|
const onSuccess = jest.fn().mockResolvedValue(undefined);
|
|
|
|
const { result } = renderHook(() => useStorageConfig());
|
|
|
|
act(() => {
|
|
result.current.setStorageBackend('indexeddb');
|
|
});
|
|
|
|
await act(async () => {
|
|
await result.current.handleSaveStorageConfig(onSuccess);
|
|
});
|
|
|
|
expect(onSuccess).toHaveBeenCalled();
|
|
});
|
|
|
|
it('should not call onSuccess if save fails', async () => {
|
|
const onSuccess = jest.fn();
|
|
const { result } = renderHook(() => useStorageConfig());
|
|
|
|
act(() => {
|
|
result.current.setStorageBackend('flask');
|
|
result.current.setFlaskUrl('');
|
|
});
|
|
|
|
await act(async () => {
|
|
await result.current.handleSaveStorageConfig(onSuccess);
|
|
});
|
|
|
|
expect(onSuccess).not.toHaveBeenCalled();
|
|
});
|
|
});
|
|
|
|
describe('state setters', () => {
|
|
it('should update storage backend', () => {
|
|
const { result } = renderHook(() => useStorageConfig());
|
|
|
|
act(() => {
|
|
result.current.setStorageBackend('flask');
|
|
});
|
|
|
|
expect(result.current.storageBackend).toBe('flask');
|
|
});
|
|
|
|
it('should update Flask URL', () => {
|
|
const { result } = renderHook(() => useStorageConfig());
|
|
|
|
act(() => {
|
|
result.current.setFlaskUrl('http://api.example.com:5000');
|
|
});
|
|
|
|
expect(result.current.flaskUrl).toBe('http://api.example.com:5000');
|
|
});
|
|
|
|
it('should update connection status', () => {
|
|
const { result } = renderHook(() => useStorageConfig());
|
|
|
|
act(() => {
|
|
result.current.setFlaskConnectionStatus('connected');
|
|
});
|
|
|
|
expect(result.current.flaskConnectionStatus).toBe('connected');
|
|
});
|
|
});
|
|
|
|
describe('complex scenarios', () => {
|
|
it('should handle full save workflow', async () => {
|
|
const mockAdapter = {
|
|
testConnection: jest.fn().mockResolvedValue(true),
|
|
};
|
|
(storage.FlaskStorageAdapter as any) = jest.fn(() => mockAdapter);
|
|
(storage.saveStorageConfig as jest.Mock).mockImplementation();
|
|
|
|
const onSuccess = jest.fn().mockResolvedValue(undefined);
|
|
|
|
const { result } = renderHook(() => useStorageConfig());
|
|
|
|
act(() => {
|
|
result.current.loadConfig();
|
|
result.current.setStorageBackend('flask');
|
|
result.current.setFlaskUrl('http://localhost:5000');
|
|
});
|
|
|
|
await act(async () => {
|
|
await result.current.handleSaveStorageConfig(onSuccess);
|
|
});
|
|
|
|
expect(storage.saveStorageConfig).toHaveBeenCalled();
|
|
expect(onSuccess).toHaveBeenCalled();
|
|
expect(toast.success).toHaveBeenCalled();
|
|
});
|
|
|
|
it('should handle backend switching', () => {
|
|
const { result } = renderHook(() => useStorageConfig());
|
|
|
|
act(() => {
|
|
result.current.setStorageBackend('indexeddb');
|
|
});
|
|
|
|
expect(result.current.storageBackend).toBe('indexeddb');
|
|
|
|
act(() => {
|
|
result.current.setStorageBackend('flask');
|
|
});
|
|
|
|
expect(result.current.storageBackend).toBe('flask');
|
|
});
|
|
});
|
|
});
|