[READ-ONLY] Mirror of https://github.com/mrgnw/cv.
0

Configure Feed

Select the types of activity you want to include in your feed.

cv / test-experience.mjs
7.7 kB 202 lines
1#!/usr/bin/env node 2import { readFileSync } from 'fs'; 3import { join, dirname } from 'path'; 4import { fileURLToPath } from 'url'; 5import JSON5 from 'json5'; 6 7const __dirname = dirname(fileURLToPath(import.meta.url)); 8 9// Colors for output 10const colors = { 11 reset: '\x1b[0m', 12 red: '\x1b[31m', 13 green: '\x1b[32m', 14 yellow: '\x1b[33m', 15 blue: '\x1b[34m', 16 cyan: '\x1b[36m', 17 bold: '\x1b[1m' 18}; 19 20function log(message, color = 'reset') { 21 console.log(`${colors[color]}${message}${colors.reset}`); 22} 23 24function loadJsonFile(filePath) { 25 try { 26 const content = readFileSync(filePath, 'utf-8'); 27 const cleanContent = content.replace(/^\uFEFF/, ''); // Remove BOM 28 return JSON5.parse(cleanContent); 29 } catch (error) { 30 log(`❌ Error loading ${filePath}: ${error.message}`, 'red'); 31 return null; 32 } 33} 34 35function testExperienceData() { 36 log('\n🔍 Testing Experience Data Integration', 'bold'); 37 log('=====================================\n'); 38 39 // Load the files 40 const mainJsonPath = join(__dirname, 'src/lib/versions/main.json'); 41 const experienceJsonPath = join(__dirname, 'src/lib/Experience.json5'); 42 const bitpandaJsonPath = join(__dirname, 'src/lib/versions/data/bitpanda.json5'); 43 44 const mainData = loadJsonFile(mainJsonPath); 45 const experienceData = loadJsonFile(experienceJsonPath); 46 const bitpandaData = loadJsonFile(bitpandaJsonPath); 47 48 if (!mainData || !experienceData) { 49 log('❌ Failed to load required files', 'red'); 50 return false; 51 } 52 53 let allTestsPassed = true; 54 55 // Test 1: Check if main.json has the correct National Care Dental end date 56 log('📋 Test 1: National Care Dental End Date in main.json', 'cyan'); 57 const mainNCD = mainData.experience.find(exp => exp.company === 'National Care Dental'); 58 if (mainNCD) { 59 if (mainNCD.end === '2025-03-17') { 60 log(`✅ National Care Dental end date is correct: ${mainNCD.end}`, 'green'); 61 } else { 62 log(`❌ National Care Dental end date is incorrect: ${mainNCD.end} (expected: 2025-03-17)`, 'red'); 63 allTestsPassed = false; 64 } 65 } else { 66 log('❌ National Care Dental not found in main.json', 'red'); 67 allTestsPassed = false; 68 } 69 70 // Test 2: Check if Experience.json5 has the correct National Care Dental end date 71 log('\n📋 Test 2: National Care Dental End Date in Experience.json5', 'cyan'); 72 const expNCD = experienceData.experience.find(exp => exp.company === 'National Care Dental'); 73 if (expNCD) { 74 if (expNCD.end === '2025-03-17') { 75 log(`✅ National Care Dental end date is correct: ${expNCD.end}`, 'green'); 76 } else { 77 log(`❌ National Care Dental end date is incorrect: ${expNCD.end} (expected: 2025-03-17)`, 'red'); 78 allTestsPassed = false; 79 } 80 } else { 81 log('❌ National Care Dental not found in Experience.json5', 'red'); 82 allTestsPassed = false; 83 } 84 85 // Test 3: Compare data between main.json and Experience.json5 86 log('\n📋 Test 3: Data Consistency Between Files', 'cyan'); 87 const mainCompanies = mainData.experience.map(exp => exp.company); 88 const expCompanies = experienceData.experience.map(exp => exp.company); 89 90 log(`Main.json companies: ${mainCompanies.join(', ')}`); 91 log(`Experience.json5 companies: ${expCompanies.join(', ')}`); 92 93 // Check if there's overlap 94 const hasOverlap = mainCompanies.some(company => expCompanies.includes(company)); 95 if (hasOverlap) { 96 log('✅ Files have overlapping companies', 'green'); 97 } else { 98 log('⚠️ Files have no overlapping companies - Experience.json5 might not be integrated', 'yellow'); 99 } 100 101 // Test 4: Check chronological order 102 log('\n📋 Test 4: Chronological Order in main.json', 'cyan'); 103 let chronologicallyCorrect = true; 104 for (let i = 1; i < mainData.experience.length; i++) { 105 const current = new Date(mainData.experience[i].start); 106 const previous = new Date(mainData.experience[i-1].start); 107 108 if (current > previous) { 109 log(`❌ Chronological order error: ${mainData.experience[i].company} (${mainData.experience[i].start}) should not be after ${mainData.experience[i-1].company} (${mainData.experience[i-1].start})`, 'red'); 110 chronologicallyCorrect = false; 111 allTestsPassed = false; 112 } 113 } 114 if (chronologicallyCorrect) { 115 log('✅ Experience entries are in correct chronological order (newest first)', 'green'); 116 } 117 118 // Test 5: Check if CGI is the current role 119 log('\n📋 Test 5: Current Role Verification', 'cyan'); 120 const currentRole = mainData.experience[0]; // Should be the first (most recent) entry 121 if (currentRole.company === 'CGI' && !currentRole.end) { 122 log(`✅ Current role is correct: ${currentRole.title} at ${currentRole.company} (started ${currentRole.start})`, 'green'); 123 } else { 124 log(`❌ Current role issue: ${currentRole.title} at ${currentRole.company} (end: ${currentRole.end || 'ongoing'})`, 'red'); 125 allTestsPassed = false; 126 } 127 128 // Test 6: Required fields validation 129 log('\n📋 Test 6: Required Fields Validation', 'cyan'); 130 let fieldsValid = true; 131 mainData.experience.forEach((exp, index) => { 132 const required = ['title', 'company', 'start', 'achievements']; 133 required.forEach(field => { 134 if (!exp[field]) { 135 log(`❌ Missing ${field} in experience[${index}] (${exp.company || 'unknown'})`, 'red'); 136 fieldsValid = false; 137 allTestsPassed = false; 138 } 139 }); 140 141 if (exp.achievements && !Array.isArray(exp.achievements)) { 142 log(`❌ Achievements should be an array in experience[${index}] (${exp.company})`, 'red'); 143 fieldsValid = false; 144 allTestsPassed = false; 145 } 146 }); 147 if (fieldsValid) { 148 log('✅ All required fields are present and valid', 'green'); 149 } 150 151 // Test 7: Bitpanda version integration 152 if (bitpandaData) { 153 log('\n📋 Test 7: Bitpanda Version Integration', 'cyan'); 154 log(`Bitpanda version has company: ${bitpandaData.company}`); 155 log(`Bitpanda version has title: ${bitpandaData.title}`); 156 log(`Bitpanda version has ${bitpandaData.experience ? bitpandaData.experience.length : 0} experience entries`); 157 158 if (bitpandaData.company === 'Bitpanda' && bitpandaData.title) { 159 log('✅ Bitpanda version has correct company and title customization', 'green'); 160 } else { 161 log('⚠️ Bitpanda version customization might be incomplete', 'yellow'); 162 } 163 } 164 165 // Summary 166 log('\n🏁 Test Summary', 'bold'); 167 log('=============='); 168 if (allTestsPassed) { 169 log('✅ All tests passed! Experience data appears to be correctly configured.', 'green'); 170 } else { 171 log('❌ Some tests failed. There may be issues with experience data integration.', 'red'); 172 } 173 174 // Recommendations 175 log('\n💡 Integration Analysis', 'bold'); 176 log('======================'); 177 178 if (mainNCD && expNCD) { 179 if (mainNCD.end === expNCD.end) { 180 log('✅ National Care Dental end dates are consistent between files', 'green'); 181 } else { 182 log('⚠️ National Care Dental end dates differ between main.json and Experience.json5', 'yellow'); 183 log(` main.json: ${mainNCD.end}`, 'yellow'); 184 log(` Experience.json5: ${expNCD.end}`, 'yellow'); 185 } 186 } 187 188 if (!hasOverlap) { 189 log('\n🔧 Recommendation: Experience.json5 Integration', 'yellow'); 190 log(' Experience.json5 appears to be a separate data source that is not'); 191 log(' being used in the main CV rendering. Consider either:'); 192 log(' 1. Updating main.json to match Experience.json5'); 193 log(' 2. Modifying versionReader.ts to use Experience.json5 as the base'); 194 log(' 3. Creating a script to sync data between files'); 195 } 196 197 return allTestsPassed; 198} 199 200// Run the tests 201const success = testExperienceData(); 202process.exit(success ? 0 : 1);