chore: initialize project repository with core extension files
- Add .gitignore to exclude node_modules, dist, logs, and system files - Add comprehensive project documentation including README, deployment guide, and development setup - Add .kiro project specifications for amazon-product-bar-extension, appwrite-cloud-storage, appwrite-userid-repair, blacklist-feature, and enhanced-item-management - Add .kiro steering documents for product, structure, styling, and tech guidelines - Add VSCode settings configuration for consistent development environment - Add manifest.json and babel/vite configuration for extension build setup - Add complete source code implementation including AppWrite integration, storage managers, UI components, and services - Add comprehensive test suite with Jest configuration and 30+ test files covering all major modules - Add test HTML files for integration testing and validation - Add coverage reports and build validation scripts - Add AppWrite setup and repair documentation for database schema management - Add migration guides and responsive accessibility implementation documentation - Establish foundation for Amazon product bar extension with full feature set including blacklist management, enhanced item workflows, and real-time synchronization
This commit is contained in:
109
src/__tests__/ErrorHandler.test.js
Normal file
109
src/__tests__/ErrorHandler.test.js
Normal file
@@ -0,0 +1,109 @@
|
||||
/**
|
||||
* ErrorHandler Tests - Core functionality tests
|
||||
* Requirements: 7.1, 7.2, 7.3, 7.4, 7.5, 7.6
|
||||
*/
|
||||
import { jest, describe, test, expect, beforeAll, beforeEach, afterEach } from '@jest/globals';
|
||||
|
||||
describe('ErrorHandler', () => {
|
||||
let ErrorHandler;
|
||||
let errorHandler;
|
||||
let handler;
|
||||
|
||||
beforeAll(async () => {
|
||||
const module = await import('../ErrorHandler.js');
|
||||
ErrorHandler = module.ErrorHandler;
|
||||
errorHandler = module.errorHandler;
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
handler = new ErrorHandler();
|
||||
jest.clearAllMocks();
|
||||
jest.spyOn(console, 'error').mockImplementation(() => {});
|
||||
jest.spyOn(console, 'warn').mockImplementation(() => {});
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
jest.restoreAllMocks();
|
||||
});
|
||||
|
||||
describe('Error Classification', () => {
|
||||
test('should classify network errors correctly', () => {
|
||||
const networkError = new Error('Network request failed');
|
||||
const processed = handler.handleError(networkError, { component: 'test' });
|
||||
expect(processed.type).toBe(handler.errorTypes.NETWORK);
|
||||
});
|
||||
|
||||
test('should classify API key errors correctly', () => {
|
||||
const apiKeyError = new Error('Invalid API key');
|
||||
const processed = handler.handleError(apiKeyError, { component: 'test' });
|
||||
expect(processed.type).toBe(handler.errorTypes.API_KEY);
|
||||
});
|
||||
|
||||
test('should classify timeout errors correctly', () => {
|
||||
const timeoutError = new Error('Request timeout');
|
||||
const processed = handler.handleError(timeoutError, { component: 'test' });
|
||||
expect(processed.type).toBe(handler.errorTypes.TIMEOUT);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Error Processing', () => {
|
||||
test('should process Error objects correctly', () => {
|
||||
const error = new Error('Test error message');
|
||||
const processed = handler.handleError(error, {
|
||||
component: 'TestComponent',
|
||||
operation: 'testOperation'
|
||||
});
|
||||
|
||||
expect(processed.originalMessage).toBe('Test error message');
|
||||
expect(processed.component).toBe('TestComponent');
|
||||
expect(processed.operation).toBe('testOperation');
|
||||
});
|
||||
});
|
||||
|
||||
describe('Retry Logic', () => {
|
||||
test('should execute operation successfully on first try', async () => {
|
||||
const mockOperation = jest.fn().mockResolvedValue('success');
|
||||
|
||||
const result = await handler.executeWithRetry(mockOperation, {
|
||||
component: 'test',
|
||||
operationName: 'testOp'
|
||||
});
|
||||
|
||||
expect(result.success).toBe(true);
|
||||
expect(result.data).toBe('success');
|
||||
expect(result.attempts).toBe(1);
|
||||
});
|
||||
});
|
||||
|
||||
describe('AI Service Fallback', () => {
|
||||
test('should provide fallback title suggestions', () => {
|
||||
const originalTitle = 'Samsung Galaxy S21 Ultra 5G Smartphone 128GB';
|
||||
const aiError = new Error('Mistral AI unavailable');
|
||||
|
||||
const fallback = handler.handleAIServiceFallback(originalTitle, aiError);
|
||||
|
||||
expect(fallback.success).toBe(false);
|
||||
expect(fallback.usedFallback).toBe(true);
|
||||
expect(fallback.titleSuggestions).toHaveLength(3);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Extraction Fallback', () => {
|
||||
test('should provide extraction fallback with manual input option', () => {
|
||||
const url = 'https://amazon.de/dp/B08N5WRWNW';
|
||||
const extractionError = new Error('Could not extract product data');
|
||||
|
||||
const fallback = handler.handleExtractionFallback(url, extractionError);
|
||||
|
||||
expect(fallback.success).toBe(false);
|
||||
expect(fallback.requiresManualInput).toBe(true);
|
||||
expect(fallback.url).toBe(url);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Singleton Instance', () => {
|
||||
test('should export singleton instance', () => {
|
||||
expect(errorHandler).toBeInstanceOf(ErrorHandler);
|
||||
});
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user