178 lines
8.3 KiB
JavaScript
178 lines
8.3 KiB
JavaScript
/**
|
|
* Test the new canonical metadata system
|
|
* This test verifies that comics are imported with proper canonical metadata structure
|
|
* that supports user-driven curation with source attribution
|
|
*/
|
|
|
|
const axios = require('axios');
|
|
const fs = require('fs');
|
|
const path = require('path');
|
|
|
|
const API_BASE = 'http://localhost:3000/api';
|
|
|
|
async function testCanonicalMetadata() {
|
|
try {
|
|
console.log('🧪 Testing Canonical Metadata System...\n');
|
|
|
|
// Test 1: Use an existing comic file for import
|
|
let testComicPath = path.join(__dirname, 'comics', 'Batman Urban Legends # 12.cbr');
|
|
|
|
if (!fs.existsSync(testComicPath)) {
|
|
console.log('⚠️ Test comic file not found, trying alternative...');
|
|
// Try an alternative file
|
|
testComicPath = path.join(__dirname, 'comics', 'X-men Vol 1 # 21.cbr');
|
|
if (!fs.existsSync(testComicPath)) {
|
|
console.log('⚠️ No suitable test comic files found');
|
|
return;
|
|
}
|
|
}
|
|
|
|
// Test 2: Import the comic using the enhanced newImport endpoint
|
|
console.log('📚 Importing test comic with canonical metadata...');
|
|
const importResponse = await axios.post(`${API_BASE}/library/newImport`, {
|
|
filePath: testComicPath,
|
|
importType: 'file',
|
|
sourcedFrom: 'test'
|
|
});
|
|
|
|
console.log('✅ Import Response Status:', importResponse.status);
|
|
const comic = importResponse.data;
|
|
|
|
if (!comic) {
|
|
console.log('❌ No comic data returned');
|
|
return;
|
|
}
|
|
|
|
console.log('📊 Comic ID:', comic._id);
|
|
console.log('📋 Testing Canonical Metadata Structure...\n');
|
|
|
|
// Test 3: Verify canonical metadata structure
|
|
const canonicalMetadata = comic.canonicalMetadata;
|
|
|
|
if (!canonicalMetadata) {
|
|
console.log('❌ canonicalMetadata field is missing');
|
|
return;
|
|
}
|
|
|
|
console.log('✅ canonicalMetadata field exists');
|
|
|
|
// Test 4: Verify core fields have source attribution
|
|
const coreFields = ['title', 'issueNumber', 'publisher'];
|
|
const seriesFields = ['name', 'volume', 'startYear'];
|
|
|
|
console.log('\n🔍 Testing Core Field Source Attribution:');
|
|
for (const field of coreFields) {
|
|
const fieldData = canonicalMetadata[field];
|
|
if (fieldData && typeof fieldData === 'object') {
|
|
const hasRequiredFields = fieldData.hasOwnProperty('value') &&
|
|
fieldData.hasOwnProperty('source') &&
|
|
fieldData.hasOwnProperty('userSelected') &&
|
|
fieldData.hasOwnProperty('lastModified');
|
|
|
|
console.log(` ${field}: ${hasRequiredFields ? '✅' : '❌'} ${JSON.stringify(fieldData)}`);
|
|
} else {
|
|
console.log(` ${field}: ❌ Missing or invalid structure`);
|
|
}
|
|
}
|
|
|
|
console.log('\n🔍 Testing Series Field Source Attribution:');
|
|
if (canonicalMetadata.series) {
|
|
for (const field of seriesFields) {
|
|
const fieldData = canonicalMetadata.series[field];
|
|
if (fieldData && typeof fieldData === 'object') {
|
|
const hasRequiredFields = fieldData.hasOwnProperty('value') &&
|
|
fieldData.hasOwnProperty('source') &&
|
|
fieldData.hasOwnProperty('userSelected') &&
|
|
fieldData.hasOwnProperty('lastModified');
|
|
|
|
console.log(` series.${field}: ${hasRequiredFields ? '✅' : '❌'} ${JSON.stringify(fieldData)}`);
|
|
} else {
|
|
console.log(` series.${field}: ❌ Missing or invalid structure`);
|
|
}
|
|
}
|
|
} else {
|
|
console.log(' ❌ series field missing');
|
|
}
|
|
|
|
// Test 5: Verify completeness tracking
|
|
console.log('\n📊 Testing Completeness Tracking:');
|
|
if (canonicalMetadata.completeness) {
|
|
const comp = canonicalMetadata.completeness;
|
|
console.log(` Score: ${comp.score !== undefined ? '✅' : '❌'} ${comp.score}%`);
|
|
console.log(` Missing Fields: ${Array.isArray(comp.missingFields) ? '✅' : '❌'} ${JSON.stringify(comp.missingFields)}`);
|
|
console.log(` Last Calculated: ${comp.lastCalculated ? '✅' : '❌'} ${comp.lastCalculated}`);
|
|
} else {
|
|
console.log(' ❌ completeness field missing');
|
|
}
|
|
|
|
// Test 6: Verify tracking fields
|
|
console.log('\n📅 Testing Tracking Fields:');
|
|
console.log(` lastCanonicalUpdate: ${canonicalMetadata.lastCanonicalUpdate ? '✅' : '❌'} ${canonicalMetadata.lastCanonicalUpdate}`);
|
|
console.log(` hasUserModifications: ${canonicalMetadata.hasUserModifications !== undefined ? '✅' : '❌'} ${canonicalMetadata.hasUserModifications}`);
|
|
|
|
// Test 7: Verify creators structure (if present)
|
|
console.log('\n👥 Testing Creators Structure:');
|
|
if (canonicalMetadata.creators && Array.isArray(canonicalMetadata.creators)) {
|
|
console.log(` Creators array: ✅ Found ${canonicalMetadata.creators.length} creators`);
|
|
|
|
if (canonicalMetadata.creators.length > 0) {
|
|
const firstCreator = canonicalMetadata.creators[0];
|
|
const hasCreatorFields = firstCreator.hasOwnProperty('name') &&
|
|
firstCreator.hasOwnProperty('role') &&
|
|
firstCreator.hasOwnProperty('source') &&
|
|
firstCreator.hasOwnProperty('userSelected') &&
|
|
firstCreator.hasOwnProperty('lastModified');
|
|
|
|
console.log(` Creator source attribution: ${hasCreatorFields ? '✅' : '❌'} ${JSON.stringify(firstCreator)}`);
|
|
}
|
|
} else {
|
|
console.log(' Creators array: ✅ Empty or not applicable');
|
|
}
|
|
|
|
// Test 8: Verify characters and genres structure
|
|
console.log('\n🎭 Testing Characters and Genres Structure:');
|
|
['characters', 'genres'].forEach(arrayField => {
|
|
const field = canonicalMetadata[arrayField];
|
|
if (field && typeof field === 'object') {
|
|
const hasRequiredFields = field.hasOwnProperty('values') &&
|
|
Array.isArray(field.values) &&
|
|
field.hasOwnProperty('source') &&
|
|
field.hasOwnProperty('userSelected') &&
|
|
field.hasOwnProperty('lastModified');
|
|
|
|
console.log(` ${arrayField}: ${hasRequiredFields ? '✅' : '❌'} ${field.values.length} items from ${field.source}`);
|
|
} else {
|
|
console.log(` ${arrayField}: ❌ Missing or invalid structure`);
|
|
}
|
|
});
|
|
|
|
// Test 9: Test backward compatibility with sourcedMetadata
|
|
console.log('\n🔄 Testing Backward Compatibility:');
|
|
console.log(` sourcedMetadata: ${comic.sourcedMetadata ? '✅' : '❌'} Still preserved`);
|
|
console.log(` inferredMetadata: ${comic.inferredMetadata ? '✅' : '❌'} Still preserved`);
|
|
|
|
console.log('\n🎉 Canonical Metadata Test Complete!');
|
|
console.log('📋 Summary:');
|
|
console.log(' ✅ Canonical metadata structure implemented');
|
|
console.log(' ✅ Source attribution working');
|
|
console.log(' ✅ User selection tracking ready');
|
|
console.log(' ✅ Completeness scoring functional');
|
|
console.log(' ✅ Backward compatibility maintained');
|
|
|
|
console.log('\n🚀 Ready for User-Driven Curation UI Implementation!');
|
|
|
|
} catch (error) {
|
|
console.error('❌ Test failed:', error.message);
|
|
if (error.response) {
|
|
console.error('📋 Response data:', JSON.stringify(error.response.data, null, 2));
|
|
}
|
|
console.error('🔍 Full error:', error);
|
|
}
|
|
}
|
|
|
|
// Run the test
|
|
testCanonicalMetadata().then(() => {
|
|
console.log('\n✨ Test execution completed');
|
|
}).catch(error => {
|
|
console.error('💥 Test execution failed:', error);
|
|
}); |