Files
bookmarksite/tests/verify_advanced_import.js
Rainer Koschnick 0abee5b794 Add comprehensive database setup and user management system
- Implement PostgreSQL database schema with users and bookmarks tables
- Add database connection pooling with retry logic and error handling
- Create migration system with automatic schema initialization
- Add database CLI tools for management (init, status, validate, etc.)
- Include comprehensive error handling and diagnostics
- Add development seed data and testing utilities
- Implement health monitoring and connection pool statistics
- Create detailed documentation and troubleshooting guide

Database features:
- Users table with authentication fields and email verification
- Bookmarks table with user association and metadata
- Proper indexes for performance optimization
- Automatic timestamp triggers
- Transaction support with rollback handling
- Connection pooling (20 max connections, 30s idle timeout)
- Graceful shutdown handling

CLI commands available:
- npm run db:init - Initialize database
- npm run db:status - Check database status
- npm run db:validate - Validate schema
- npm run db:test - Run database tests
- npm run db:diagnostics - Full diagnostics
2025-07-19 23:21:50 +02:00

270 lines
9.4 KiB
JavaScript
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// Verification script for advanced import/export functionality
// This script tests the new features without requiring a browser
// Mock DOM elements and browser APIs
global.document = {
getElementById: (id) => ({
value: '',
checked: true,
style: { display: 'none' },
innerHTML: '',
textContent: '',
addEventListener: () => {},
classList: { add: () => {}, remove: () => {} },
setAttribute: () => {},
getAttribute: () => null
}),
querySelectorAll: () => [],
querySelector: () => null,
createElement: () => ({
className: '',
innerHTML: '',
appendChild: () => {},
addEventListener: () => {}
})
};
global.window = {
open: () => {},
addEventListener: () => {}
};
global.localStorage = {
getItem: () => null,
setItem: () => {},
removeItem: () => {}
};
global.alert = console.log;
global.confirm = () => true;
global.prompt = () => 'test';
// Mock FileReader
global.FileReader = class {
readAsText() {
setTimeout(() => {
this.onload({ target: { result: '{"test": "data"}' } });
}, 10);
}
};
// Mock DOMParser
global.DOMParser = class {
parseFromString(content, type) {
return {
querySelectorAll: () => [],
querySelector: () => null
};
}
};
global.btoa = (str) => Buffer.from(str).toString('base64');
global.atob = (str) => Buffer.from(str, 'base64').toString();
// Load the BookmarkManager class
const fs = require('fs');
const scriptContent = fs.readFileSync('script.js', 'utf8');
// Extract just the BookmarkManager class definition
const classMatch = scriptContent.match(/class BookmarkManager \{[\s\S]*?\n\}/);
if (!classMatch) {
console.error('Could not extract BookmarkManager class');
process.exit(1);
}
// Evaluate the class
eval(classMatch[0]);
// Test the advanced import functionality
async function testAdvancedImport() {
console.log('🧪 Testing Advanced Import/Export Features...\n');
const manager = new BookmarkManager();
// Test 1: Chrome bookmarks parsing
console.log('1⃣ Testing Chrome bookmarks parsing...');
try {
const sampleChromeData = {
"roots": {
"bookmark_bar": {
"children": [
{
"type": "url",
"name": "Google",
"url": "https://www.google.com",
"date_added": "13285166270000000"
},
{
"type": "folder",
"name": "Development",
"children": [
{
"type": "url",
"name": "GitHub",
"url": "https://github.com",
"date_added": "13285166280000000"
}
]
}
]
}
}
};
const bookmarks = manager.parseChromeBookmarks(JSON.stringify(sampleChromeData));
console.log(` ✅ Parsed ${bookmarks.length} bookmarks from Chrome format`);
console.log(` 📁 Folders: ${[...new Set(bookmarks.map(b => b.folder || 'Root'))].join(', ')}`);
} catch (error) {
console.log(` ❌ Chrome parsing failed: ${error.message}`);
}
// Test 2: Firefox bookmarks parsing
console.log('\n2⃣ Testing Firefox bookmarks parsing...');
try {
const sampleFirefoxData = [
{
"type": "text/x-moz-place-container",
"title": "Bookmarks Menu",
"children": [
{
"type": "text/x-moz-place",
"title": "Mozilla Firefox",
"uri": "https://www.mozilla.org/firefox/",
"dateAdded": 1642534567890000
},
{
"type": "text/x-moz-place-container",
"title": "Development",
"children": [
{
"type": "text/x-moz-place",
"title": "MDN Web Docs",
"uri": "https://developer.mozilla.org/",
"dateAdded": 1642534577890000
}
]
}
]
}
];
const bookmarks = manager.parseFirefoxBookmarks(JSON.stringify(sampleFirefoxData));
console.log(` ✅ Parsed ${bookmarks.length} bookmarks from Firefox format`);
console.log(` 📁 Folders: ${[...new Set(bookmarks.map(b => b.folder || 'Root'))].join(', ')}`);
} catch (error) {
console.log(` ❌ Firefox parsing failed: ${error.message}`);
}
// Test 3: Format detection
console.log('\n3⃣ Testing format detection...');
try {
const chromeFormat = manager.detectFileFormat(
{ name: 'bookmarks.json' },
JSON.stringify({ roots: { bookmark_bar: {} } })
);
const firefoxFormat = manager.detectFileFormat(
{ name: 'bookmarks.json' },
JSON.stringify([{ type: 'text/x-moz-place-container' }])
);
const htmlFormat = manager.detectFileFormat(
{ name: 'bookmarks.html' },
'<!DOCTYPE NETSCAPE-Bookmark-file-1>'
);
console.log(` ✅ Chrome format detected: ${chromeFormat === 'chrome'}`);
console.log(` ✅ Firefox format detected: ${firefoxFormat === 'firefox'}`);
console.log(` ✅ HTML format detected: ${htmlFormat === 'netscape'}`);
} catch (error) {
console.log(` ❌ Format detection failed: ${error.message}`);
}
// Test 4: Duplicate detection
console.log('\n4⃣ Testing enhanced duplicate detection...');
try {
// Add some existing bookmarks
manager.bookmarks = [
{
id: 'existing1',
title: 'Google Search Engine',
url: 'https://www.google.com/',
folder: 'Search',
addDate: Date.now() - 1000000,
status: 'valid'
}
];
const testBookmark = {
title: 'Google',
url: 'https://google.com',
folder: 'Web',
addDate: Date.now(),
status: 'unknown'
};
const duplicate = manager.findDuplicateBookmark(testBookmark, true, true);
const similarity = manager.calculateStringSimilarity('Google Search Engine', 'Google');
console.log(` ✅ Duplicate detection working: ${duplicate ? 'Found duplicate' : 'No duplicate'}`);
console.log(` 📊 Title similarity: ${Math.round(similarity * 100)}%`);
console.log(` 🔗 URL normalization: ${manager.normalizeUrl('https://www.google.com/') === manager.normalizeUrl('https://google.com')}`);
} catch (error) {
console.log(` ❌ Duplicate detection failed: ${error.message}`);
}
// Test 5: Import analysis
console.log('\n5⃣ Testing import analysis...');
try {
const importData = {
bookmarks: [
{
id: 'import1',
title: 'New Site',
url: 'https://example.com',
folder: 'Examples',
addDate: Date.now(),
status: 'unknown'
},
{
id: 'import2',
title: 'Google Clone',
url: 'https://google.com',
folder: 'Search',
addDate: Date.now(),
status: 'unknown'
}
],
format: 'test',
originalCount: 2
};
const analysis = manager.analyzeImportData(importData, 'merge');
console.log(` ✅ Analysis completed:`);
console.log(` 📊 New bookmarks: ${analysis.newBookmarks.length}`);
console.log(` 🔄 Duplicates: ${analysis.duplicates.length}`);
console.log(` 📁 Folders: ${analysis.folders.length}`);
} catch (error) {
console.log(` ❌ Import analysis failed: ${error.message}`);
}
// Test 6: Sync functionality
console.log('\n6⃣ Testing sync functionality...');
try {
const deviceId = manager.getDeviceId();
const syncData = manager.exportForSync();
const dataHash = manager.calculateDataHash();
const compressed = manager.compressAndEncodeData({ test: 'data' });
const decompressed = manager.decodeAndDecompressData(compressed);
console.log(` ✅ Device ID generated: ${deviceId.startsWith('device_')}`);
console.log(` 📦 Sync export working: ${syncData.bookmarks.length >= 0}`);
console.log(` 🔢 Data hash generated: ${typeof dataHash === 'string'}`);
console.log(` 🗜️ Compression working: ${decompressed.test === 'data'}`);
} catch (error) {
console.log(` ❌ Sync functionality failed: ${error.message}`);
}
console.log('\n🎉 Advanced Import/Export Features Testing Complete!');
}
// Run the tests
testAdvancedImport().catch(console.error);