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:
587
test-enhanced-item-workflow-verification.html
Normal file
587
test-enhanced-item-workflow-verification.html
Normal file
@@ -0,0 +1,587 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="de">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Enhanced Item Workflow Verification</title>
|
||||
<style>
|
||||
body {
|
||||
margin: 0;
|
||||
padding: 20px;
|
||||
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
|
||||
background: #f5f5f5;
|
||||
}
|
||||
|
||||
.test-container {
|
||||
max-width: 1000px;
|
||||
margin: 0 auto;
|
||||
background: white;
|
||||
border-radius: 12px;
|
||||
padding: 2rem;
|
||||
box-shadow: 0 4px 20px rgba(0,0,0,0.1);
|
||||
}
|
||||
|
||||
.test-button {
|
||||
background: #ff9900;
|
||||
color: white;
|
||||
border: none;
|
||||
padding: 12px 24px;
|
||||
border-radius: 8px;
|
||||
cursor: pointer;
|
||||
margin: 0.5rem;
|
||||
font-size: 1rem;
|
||||
}
|
||||
|
||||
.test-button:hover {
|
||||
background: #ff7700;
|
||||
}
|
||||
|
||||
.workflow-container {
|
||||
border: 2px solid #007bff;
|
||||
border-radius: 8px;
|
||||
padding: 1rem;
|
||||
margin: 1rem 0;
|
||||
min-height: 300px;
|
||||
background: white;
|
||||
}
|
||||
|
||||
.status-message {
|
||||
padding: 1rem;
|
||||
margin: 1rem 0;
|
||||
border-radius: 6px;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.status-success {
|
||||
background: #d4edda;
|
||||
border: 1px solid #c3e6cb;
|
||||
color: #155724;
|
||||
}
|
||||
|
||||
.status-error {
|
||||
background: #f8d7da;
|
||||
border: 1px solid #f5c6cb;
|
||||
color: #721c24;
|
||||
}
|
||||
|
||||
.status-info {
|
||||
background: #d1ecf1;
|
||||
border: 1px solid #bee5eb;
|
||||
color: #0c5460;
|
||||
}
|
||||
|
||||
.status-warning {
|
||||
background: #fff3cd;
|
||||
border: 1px solid #ffeaa7;
|
||||
color: #856404;
|
||||
}
|
||||
|
||||
.progress-container {
|
||||
background: #f8f9fa;
|
||||
border-radius: 8px;
|
||||
padding: 1rem;
|
||||
margin: 1rem 0;
|
||||
}
|
||||
|
||||
.progress-step {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 0.5rem;
|
||||
margin: 0.25rem 0;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.progress-step.active {
|
||||
background: #fff3cd;
|
||||
border-left: 4px solid #ffc107;
|
||||
}
|
||||
|
||||
.progress-step.completed {
|
||||
background: #d4edda;
|
||||
border-left: 4px solid #28a745;
|
||||
}
|
||||
|
||||
.progress-step.error {
|
||||
background: #f8d7da;
|
||||
border-left: 4px solid #dc3545;
|
||||
}
|
||||
|
||||
.step-icon {
|
||||
font-size: 1.2rem;
|
||||
margin-right: 0.5rem;
|
||||
}
|
||||
|
||||
.step-name {
|
||||
flex: 1;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.step-status {
|
||||
font-size: 0.9rem;
|
||||
color: #666;
|
||||
}
|
||||
|
||||
/* Title Selection Styles */
|
||||
.title-selection-container {
|
||||
border: 2px solid #28a745;
|
||||
border-radius: 8px;
|
||||
padding: 1rem;
|
||||
margin: 1rem 0;
|
||||
background: #f8fff8;
|
||||
}
|
||||
|
||||
.title-selection-header h3 {
|
||||
margin: 0 0 1rem 0;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.title-option {
|
||||
border: 1px solid #ddd;
|
||||
border-radius: 6px;
|
||||
padding: 1rem;
|
||||
margin: 0.5rem 0;
|
||||
cursor: pointer;
|
||||
transition: all 0.2s ease;
|
||||
background: white;
|
||||
}
|
||||
|
||||
.title-option:hover {
|
||||
border-color: #ff9900;
|
||||
box-shadow: 0 2px 8px rgba(255, 153, 0, 0.2);
|
||||
}
|
||||
|
||||
.title-option.selected {
|
||||
border-color: #28a745;
|
||||
background: #f8fff8;
|
||||
box-shadow: 0 2px 8px rgba(40, 167, 69, 0.2);
|
||||
}
|
||||
|
||||
.title-option.disabled {
|
||||
opacity: 0.5;
|
||||
cursor: not-allowed;
|
||||
background: #f5f5f5;
|
||||
}
|
||||
|
||||
.option-label {
|
||||
font-weight: bold;
|
||||
color: #666;
|
||||
font-size: 0.9rem;
|
||||
display: block;
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
|
||||
.option-text {
|
||||
color: #333;
|
||||
line-height: 1.4;
|
||||
}
|
||||
|
||||
.selection-actions {
|
||||
display: flex;
|
||||
gap: 1rem;
|
||||
margin-top: 1rem;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.confirm-selection-btn, .skip-ai-btn {
|
||||
padding: 10px 20px;
|
||||
border: none;
|
||||
border-radius: 6px;
|
||||
cursor: pointer;
|
||||
font-size: 1rem;
|
||||
}
|
||||
|
||||
.confirm-selection-btn {
|
||||
background: #28a745;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.confirm-selection-btn:hover {
|
||||
background: #218838;
|
||||
}
|
||||
|
||||
.skip-ai-btn {
|
||||
background: #6c757d;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.skip-ai-btn:hover {
|
||||
background: #5a6268;
|
||||
}
|
||||
|
||||
.console-output {
|
||||
background: #1e1e1e;
|
||||
color: #d4d4d4;
|
||||
padding: 1rem;
|
||||
border-radius: 6px;
|
||||
font-family: 'Courier New', monospace;
|
||||
font-size: 0.9rem;
|
||||
max-height: 300px;
|
||||
overflow-y: auto;
|
||||
margin: 1rem 0;
|
||||
}
|
||||
|
||||
.console-error {
|
||||
color: #f48771;
|
||||
}
|
||||
|
||||
.console-warning {
|
||||
color: #dcdcaa;
|
||||
}
|
||||
|
||||
.console-success {
|
||||
color: #4ec9b0;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="test-container">
|
||||
<h1>🔧 Enhanced Item Workflow Verification</h1>
|
||||
|
||||
<div class="status-info status-message">
|
||||
<strong>Ziel:</strong> Vollständige Verifikation der Fehlerbehebung für "Unerwarteter Fehler beim Erstellen des Enhanced Items"
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<h3>Test Scenarios</h3>
|
||||
<button class="test-button" onclick="testCompleteWorkflow()">Complete Workflow Test</button>
|
||||
<button class="test-button" onclick="testTitleSelectionOnly()">Title Selection Only</button>
|
||||
<button class="test-button" onclick="testErrorScenarios()">Error Scenarios</button>
|
||||
<button class="test-button" onclick="clearTest()">Clear</button>
|
||||
</div>
|
||||
|
||||
<div class="progress-container" id="progressContainer" style="display: none;">
|
||||
<h4>Workflow Progress</h4>
|
||||
<div id="progressSteps"></div>
|
||||
</div>
|
||||
|
||||
<div class="workflow-container" id="testContainer">
|
||||
<h4>Test Area</h4>
|
||||
<p>Wählen Sie einen Test aus, um zu beginnen...</p>
|
||||
</div>
|
||||
|
||||
<div id="statusContainer"></div>
|
||||
|
||||
<div class="console-output" id="consoleOutput" style="display: none;">
|
||||
<h4>Console Output</h4>
|
||||
<div id="consoleContent"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script type="module">
|
||||
// Mock environment setup
|
||||
const mockStorage = {
|
||||
data: {},
|
||||
getItem(key) { return this.data[key] || null; },
|
||||
setItem(key, value) { this.data[key] = value; },
|
||||
removeItem(key) { delete this.data[key]; },
|
||||
clear() { this.data = {}; }
|
||||
};
|
||||
|
||||
if (typeof localStorage === 'undefined') {
|
||||
window.localStorage = mockStorage;
|
||||
}
|
||||
|
||||
// Mock event bus
|
||||
window.amazonExtEventBus = {
|
||||
events: {},
|
||||
emit(event, data) {
|
||||
logToConsole(`Event: ${event}`, 'info');
|
||||
console.log('Event:', event, data);
|
||||
},
|
||||
on(event, callback) { }
|
||||
};
|
||||
|
||||
// Console logging
|
||||
function logToConsole(message, type = 'info') {
|
||||
const consoleOutput = document.getElementById('consoleOutput');
|
||||
const consoleContent = document.getElementById('consoleContent');
|
||||
|
||||
consoleOutput.style.display = 'block';
|
||||
|
||||
const logEntry = document.createElement('div');
|
||||
logEntry.className = `console-${type}`;
|
||||
logEntry.textContent = `[${new Date().toLocaleTimeString()}] ${message}`;
|
||||
consoleContent.appendChild(logEntry);
|
||||
|
||||
// Auto-scroll to bottom
|
||||
consoleContent.scrollTop = consoleContent.scrollHeight;
|
||||
}
|
||||
|
||||
// Load modules
|
||||
let TitleSelectionManager, EnhancedAddItemWorkflow, ProductExtractor, MistralAIService, EnhancedStorageManager, UrlValidator, errorHandler;
|
||||
|
||||
async function loadModules() {
|
||||
try {
|
||||
logToConsole('Loading modules...', 'info');
|
||||
|
||||
const titleModule = await import('./src/TitleSelectionManager.js');
|
||||
TitleSelectionManager = titleModule.TitleSelectionManager;
|
||||
logToConsole('✅ TitleSelectionManager loaded', 'success');
|
||||
|
||||
const workflowModule = await import('./src/EnhancedAddItemWorkflow.js');
|
||||
EnhancedAddItemWorkflow = workflowModule.EnhancedAddItemWorkflow;
|
||||
logToConsole('✅ EnhancedAddItemWorkflow loaded', 'success');
|
||||
|
||||
const extractorModule = await import('./src/ProductExtractor.js');
|
||||
ProductExtractor = extractorModule.ProductExtractor;
|
||||
logToConsole('✅ ProductExtractor loaded', 'success');
|
||||
|
||||
const mistralModule = await import('./src/MistralAIService.js');
|
||||
MistralAIService = mistralModule.MistralAIService;
|
||||
logToConsole('✅ MistralAIService loaded', 'success');
|
||||
|
||||
const storageModule = await import('./src/EnhancedStorageManager.js');
|
||||
EnhancedStorageManager = storageModule.EnhancedStorageManager;
|
||||
logToConsole('✅ EnhancedStorageManager loaded', 'success');
|
||||
|
||||
const urlModule = await import('./src/UrlValidator.js');
|
||||
UrlValidator = urlModule.UrlValidator;
|
||||
logToConsole('✅ UrlValidator loaded', 'success');
|
||||
|
||||
const errorModule = await import('./src/ErrorHandler.js');
|
||||
errorHandler = errorModule.errorHandler;
|
||||
logToConsole('✅ ErrorHandler loaded', 'success');
|
||||
|
||||
showStatus('✅ All modules loaded successfully', 'success');
|
||||
|
||||
} catch (error) {
|
||||
logToConsole(`❌ Failed to load modules: ${error.message}`, 'error');
|
||||
showStatus('❌ Failed to load modules: ' + error.message, 'error');
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
function showStatus(message, type = 'info') {
|
||||
const statusContainer = document.getElementById('statusContainer');
|
||||
const statusDiv = document.createElement('div');
|
||||
statusDiv.className = `status-message status-${type}`;
|
||||
statusDiv.textContent = message;
|
||||
statusContainer.appendChild(statusDiv);
|
||||
|
||||
logToConsole(message, type);
|
||||
|
||||
// Auto-remove after 5 seconds
|
||||
setTimeout(() => {
|
||||
if (statusDiv.parentNode) {
|
||||
statusDiv.parentNode.removeChild(statusDiv);
|
||||
}
|
||||
}, 5000);
|
||||
}
|
||||
|
||||
function showProgress(steps) {
|
||||
const progressContainer = document.getElementById('progressContainer');
|
||||
const progressSteps = document.getElementById('progressSteps');
|
||||
|
||||
progressContainer.style.display = 'block';
|
||||
progressSteps.innerHTML = '';
|
||||
|
||||
steps.forEach(step => {
|
||||
const stepDiv = document.createElement('div');
|
||||
stepDiv.className = `progress-step ${step.status || ''}`;
|
||||
stepDiv.innerHTML = `
|
||||
<span class="step-icon">${step.icon}</span>
|
||||
<span class="step-name">${step.name}</span>
|
||||
<span class="step-status">${step.statusText || ''}</span>
|
||||
`;
|
||||
progressSteps.appendChild(stepDiv);
|
||||
});
|
||||
}
|
||||
|
||||
window.testCompleteWorkflow = async function() {
|
||||
logToConsole('=== Testing Complete Enhanced Item Workflow ===', 'info');
|
||||
showStatus('Testing complete workflow...', 'info');
|
||||
|
||||
try {
|
||||
const container = document.getElementById('testContainer');
|
||||
container.innerHTML = '<h4>🚀 Complete Workflow Test</h4>';
|
||||
|
||||
// Show progress
|
||||
const progressSteps = [
|
||||
{ id: 'validate', name: 'URL-Validierung', icon: '🔍', status: 'active', statusText: 'In Progress...' },
|
||||
{ id: 'extract', name: 'Produktdaten extrahieren', icon: '📦', statusText: 'Waiting...' },
|
||||
{ id: 'ai', name: 'KI-Titelvorschläge generieren', icon: '🤖', statusText: 'Waiting...' },
|
||||
{ id: 'select', name: 'Titel auswählen', icon: '✏️', statusText: 'Waiting...' },
|
||||
{ id: 'save', name: 'Item speichern', icon: '💾', statusText: 'Waiting...' }
|
||||
];
|
||||
showProgress(progressSteps);
|
||||
|
||||
// Create workflow instance
|
||||
const workflow = new EnhancedAddItemWorkflow();
|
||||
|
||||
// Set up progress callback
|
||||
workflow.onProgress((progress) => {
|
||||
logToConsole(`Progress: ${progress.stepId} - ${progress.status}`, 'info');
|
||||
|
||||
// Update progress display
|
||||
const updatedSteps = progressSteps.map(step => {
|
||||
if (step.id === progress.stepId) {
|
||||
return {
|
||||
...step,
|
||||
status: progress.status,
|
||||
statusText: progress.status === 'completed' ? '✅ Completed' :
|
||||
progress.status === 'error' ? '❌ Error' :
|
||||
progress.status === 'active' ? '⏳ In Progress...' : 'Waiting...'
|
||||
};
|
||||
}
|
||||
return step;
|
||||
});
|
||||
showProgress(updatedSteps);
|
||||
});
|
||||
|
||||
// Set up completion callback
|
||||
workflow.onComplete((result) => {
|
||||
logToConsole(`Workflow completed: ${JSON.stringify(result)}`, 'success');
|
||||
showStatus('✅ Workflow completed successfully!', 'success');
|
||||
});
|
||||
|
||||
// Set up error callback
|
||||
workflow.onError((error) => {
|
||||
logToConsole(`Workflow error: ${JSON.stringify(error)}`, 'error');
|
||||
showStatus('❌ Workflow failed: ' + error.error, 'error');
|
||||
});
|
||||
|
||||
// Set up manual input callback
|
||||
workflow.onManualInput((result) => {
|
||||
logToConsole('Manual input required', 'warning');
|
||||
showStatus('⚠️ Manual input required', 'warning');
|
||||
});
|
||||
|
||||
// Test URL (this will fail extraction, triggering title selection with mock data)
|
||||
const testUrl = 'https://www.amazon.de/dp/B08TESTITEM';
|
||||
|
||||
logToConsole(`Starting workflow with URL: ${testUrl}`, 'info');
|
||||
|
||||
// Start workflow
|
||||
const result = await workflow.startWorkflow(testUrl, {
|
||||
container: container,
|
||||
allowManualFallback: true,
|
||||
settings: {
|
||||
mistralApiKey: null, // No API key to test fallback
|
||||
timeoutSeconds: 5
|
||||
}
|
||||
});
|
||||
|
||||
logToConsole(`Workflow result: ${JSON.stringify(result)}`, result.success ? 'success' : 'error');
|
||||
|
||||
} catch (error) {
|
||||
logToConsole(`❌ Complete workflow test failed: ${error.message}`, 'error');
|
||||
showStatus('❌ Complete workflow test failed: ' + error.message, 'error');
|
||||
}
|
||||
};
|
||||
|
||||
window.testTitleSelectionOnly = function() {
|
||||
logToConsole('=== Testing Title Selection Only ===', 'info');
|
||||
showStatus('Testing title selection...', 'info');
|
||||
|
||||
try {
|
||||
const container = document.getElementById('testContainer');
|
||||
container.innerHTML = '<h4>✏️ Title Selection Test</h4>';
|
||||
|
||||
const titleManager = new TitleSelectionManager();
|
||||
|
||||
// Test data
|
||||
const suggestions = [
|
||||
'ROCKBROS Fahrradhandschuhe - Premium Qualität für Herren und Damen',
|
||||
'Hochwertige MTB Handschuhe von ROCKBROS - Halbfinger Design',
|
||||
'ROCKBROS Radfahrer Handschuhe - Komfort und Grip'
|
||||
];
|
||||
const originalTitle = 'ROCKBROS Fahrradhandschuhe Herren Damen Halbfinger MTB Handschuhe Rennrad Handschuhe rutschfest Atmungsaktiv für Radsport Outdoor Sport';
|
||||
|
||||
logToConsole('Creating title selection UI...', 'info');
|
||||
|
||||
// Create UI
|
||||
const selectionUI = titleManager.createSelectionUI(suggestions, originalTitle);
|
||||
container.appendChild(selectionUI);
|
||||
|
||||
// Set up callback
|
||||
titleManager.onTitleSelected((selectedTitle) => {
|
||||
logToConsole(`✅ Title selected: ${selectedTitle}`, 'success');
|
||||
showStatus('✅ Title selected: ' + selectedTitle, 'success');
|
||||
});
|
||||
|
||||
// Show UI
|
||||
titleManager.showTitleSelection(selectionUI);
|
||||
|
||||
logToConsole('✅ Title selection UI created and displayed', 'success');
|
||||
showStatus('✅ Title selection test completed - please select a title', 'success');
|
||||
|
||||
} catch (error) {
|
||||
logToConsole(`❌ Title selection test failed: ${error.message}`, 'error');
|
||||
showStatus('❌ Title selection test failed: ' + error.message, 'error');
|
||||
}
|
||||
};
|
||||
|
||||
window.testErrorScenarios = function() {
|
||||
logToConsole('=== Testing Error Scenarios ===', 'info');
|
||||
showStatus('Testing error scenarios...', 'info');
|
||||
|
||||
try {
|
||||
const container = document.getElementById('testContainer');
|
||||
container.innerHTML = '<h4>🐛 Error Scenarios Test</h4>';
|
||||
|
||||
// Test 1: TitleSelectionManager without InteractivityEnhancer
|
||||
logToConsole('Test 1: TitleSelectionManager without InteractivityEnhancer', 'info');
|
||||
const titleManager1 = new TitleSelectionManager();
|
||||
titleManager1.interactivityEnhancer = null;
|
||||
|
||||
const ui1 = titleManager1.createSelectionUI(['Test 1', 'Test 2'], 'Original');
|
||||
titleManager1.showTitleSelection(ui1);
|
||||
logToConsole('✅ Test 1 passed - no InteractivityEnhancer', 'success');
|
||||
|
||||
// Test 2: Invalid data handling
|
||||
logToConsole('Test 2: Invalid data handling', 'info');
|
||||
const titleManager2 = new TitleSelectionManager();
|
||||
const ui2 = titleManager2.createSelectionUI(null, null);
|
||||
titleManager2.showTitleSelection(null);
|
||||
titleManager2.selectTitle(-1);
|
||||
titleManager2.selectTitle(999);
|
||||
titleManager2.confirmSelection();
|
||||
logToConsole('✅ Test 2 passed - invalid data handled', 'success');
|
||||
|
||||
// Test 3: DOM manipulation errors
|
||||
logToConsole('Test 3: DOM manipulation errors', 'info');
|
||||
const titleManager3 = new TitleSelectionManager();
|
||||
titleManager3.currentContainer = null;
|
||||
titleManager3.showTitleSelection(document.createElement('div'));
|
||||
titleManager3.showMessage('Test message', 'error');
|
||||
logToConsole('✅ Test 3 passed - DOM errors handled', 'success');
|
||||
|
||||
// Test 4: Callback errors
|
||||
logToConsole('Test 4: Callback errors', 'info');
|
||||
const titleManager4 = new TitleSelectionManager();
|
||||
titleManager4.onTitleSelected(() => {
|
||||
throw new Error('Callback error test');
|
||||
});
|
||||
titleManager4.selectedTitle = 'Test';
|
||||
titleManager4.confirmSelection();
|
||||
logToConsole('✅ Test 4 passed - callback errors handled', 'success');
|
||||
|
||||
// Display results
|
||||
container.innerHTML += '<div class="status-success status-message">✅ All error scenarios handled gracefully</div>';
|
||||
|
||||
showStatus('✅ All error scenarios tested successfully', 'success');
|
||||
|
||||
} catch (error) {
|
||||
logToConsole(`❌ Error scenarios test failed: ${error.message}`, 'error');
|
||||
showStatus('❌ Error scenarios test failed: ' + error.message, 'error');
|
||||
}
|
||||
};
|
||||
|
||||
window.clearTest = function() {
|
||||
document.getElementById('testContainer').innerHTML = '<h4>Test Area</h4><p>Wählen Sie einen Test aus, um zu beginnen...</p>';
|
||||
document.getElementById('statusContainer').innerHTML = '';
|
||||
document.getElementById('progressContainer').style.display = 'none';
|
||||
document.getElementById('consoleOutput').style.display = 'none';
|
||||
document.getElementById('consoleContent').innerHTML = '';
|
||||
console.clear();
|
||||
};
|
||||
|
||||
// Initialize
|
||||
loadModules().then(() => {
|
||||
logToConsole('🔧 Enhanced Item Workflow Verification ready', 'success');
|
||||
}).catch(error => {
|
||||
logToConsole(`❌ Initialization failed: ${error.message}`, 'error');
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user