[READ-ONLY] Mirror of https://github.com/mrgnw/cv.
1#!/usr/bin/env node
2import { spawn } from "child_process";
3import { readFileSync, existsSync } from "fs";
4import { join, dirname } from "path";
5import { fileURLToPath } from "url";
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 runCommand(command, args, cwd = __dirname) {
25 return new Promise((resolve, reject) => {
26 const child = spawn(command, args, {
27 stdio: "inherit",
28 cwd,
29 shell: true,
30 });
31
32 child.on("close", (code) => {
33 resolve(code === 0);
34 });
35
36 child.on("error", (error) => {
37 reject(error);
38 });
39 });
40}
41
42async function runTest(testName, scriptPath, description) {
43 log(`\n🧪 Running ${testName}`, "bold");
44 log(`📝 ${description}`, "blue");
45 log("─".repeat(60), "cyan");
46
47 if (!existsSync(scriptPath)) {
48 log(`❌ Test script not found: ${scriptPath}`, "red");
49 return false;
50 }
51
52 try {
53 const success = await runCommand("node", [scriptPath]);
54
55 if (success) {
56 log(`✅ ${testName} PASSED`, "green");
57 } else {
58 log(`❌ ${testName} FAILED`, "red");
59 }
60
61 return success;
62 } catch (error) {
63 log(`❌ ${testName} ERROR: ${error.message}`, "red");
64 return false;
65 }
66}
67
68async function runAllTests() {
69 log("\n🚀 Morgan's CV - Comprehensive Test Suite", "bold");
70 log("==========================================\n");
71
72 const startTime = Date.now();
73 const testResults = [];
74
75 // Test configurations
76 const tests = [
77 {
78 name: "Experience Data Integration",
79 script: "test-experience.mjs",
80 description:
81 "Validates that experience data files are consistent and properly structured",
82 },
83 {
84 name: "Version Reader Integration",
85 script: "test-version-integration.mjs",
86 description:
87 "Tests end-to-end version merging and route-level data flow",
88 },
89 {
90 name: "Experience Data Validation",
91 script: "validate-experience.mjs",
92 description:
93 "Comprehensive validation of experience data integrity and consistency",
94 },
95 {
96 name: "Content Optimization System",
97 script: "test-content-optimization.mjs",
98 description:
99 "Validates priority-based content reduction and PDF optimization features",
100 },
101 ];
102
103 // Run each test
104 for (const test of tests) {
105 const scriptPath = join(__dirname, test.script);
106 const result = await runTest(test.name, scriptPath, test.description);
107 testResults.push({ name: test.name, passed: result });
108
109 // Add separator between tests
110 if (test !== tests[tests.length - 1]) {
111 log("\n" + "═".repeat(80), "cyan");
112 }
113 }
114
115 // Summary
116 const endTime = Date.now();
117 const duration = ((endTime - startTime) / 1000).toFixed(2);
118 const passedCount = testResults.filter((r) => r.passed).length;
119 const totalCount = testResults.length;
120
121 log("\n🏁 TEST SUITE SUMMARY", "bold");
122 log("═".repeat(50), "cyan");
123 log(`⏱️ Total time: ${duration}s`);
124 log(`📊 Tests passed: ${passedCount}/${totalCount}`);
125
126 // Individual test results
127 testResults.forEach((result) => {
128 const icon = result.passed ? "✅" : "❌";
129 const color = result.passed ? "green" : "red";
130 log(`${icon} ${result.name}`, color);
131 });
132
133 // Overall result
134 const allPassed = passedCount === totalCount;
135 log("\n" + "═".repeat(50), "cyan");
136
137 if (allPassed) {
138 log("🎉 ALL TESTS PASSED!", "bold");
139 log("✅ Your CV system is working correctly", "green");
140 log("✅ Experience data flows properly through all routes", "green");
141 log(
142 "✅ National Care Dental end date (2025-03-17) is correct",
143 "green",
144 );
145 log(
146 "✅ Version customizations work without breaking base data",
147 "green",
148 );
149
150 log("\n💡 CONCLUSION:", "bold");
151 log(
152 "Your concern about experience data not making it to the main page",
153 "green",
154 );
155 log(
156 "appears to be unfounded. The system is working as expected!",
157 "green",
158 );
159 } else {
160 log("❌ SOME TESTS FAILED", "bold");
161 log(
162 "Please review the failed tests above and address the issues.",
163 "red",
164 );
165
166 const failedTests = testResults
167 .filter((r) => !r.passed)
168 .map((r) => r.name);
169 log(`\nFailed tests: ${failedTests.join(", ")}`, "yellow");
170 }
171
172 // Additional system checks
173 log("\n🔍 System Health Check", "bold");
174 log("─".repeat(30), "cyan");
175
176 // Check if main files exist
177 const criticalFiles = [
178 "src/lib/versions/main.json",
179 "src/lib/Experience.json5",
180 "src/routes/+page.svelte",
181 "src/routes/[slug]/+page.svelte",
182 "src/lib/versionReader.ts",
183 "src/lib/CV.svelte",
184 ];
185
186 let allFilesExist = true;
187 criticalFiles.forEach((file) => {
188 const fullPath = join(__dirname, file);
189 if (existsSync(fullPath)) {
190 log(`✅ ${file}`, "green");
191 } else {
192 log(`❌ ${file} - MISSING`, "red");
193 allFilesExist = false;
194 }
195 });
196
197 if (!allFilesExist) {
198 log("\n⚠️ Some critical files are missing!", "yellow");
199 allPassed = false;
200 }
201
202 // Check package.json for required dependencies
203 const packageJsonPath = join(__dirname, "package.json");
204 if (existsSync(packageJsonPath)) {
205 try {
206 const packageJson = JSON.parse(
207 readFileSync(packageJsonPath, "utf-8"),
208 );
209 const requiredDeps = ["json5", "date-fns", "svelte"];
210 const hasDeps = requiredDeps.every(
211 (dep) =>
212 packageJson.dependencies?.[dep] ||
213 packageJson.devDependencies?.[dep],
214 );
215
216 if (hasDeps) {
217 log("✅ Required dependencies present", "green");
218 } else {
219 log("❌ Some required dependencies may be missing", "red");
220 }
221 } catch (error) {
222 log("❌ Could not parse package.json", "red");
223 }
224 }
225
226 // Final recommendation
227 if (allPassed) {
228 log("\n🚀 RECOMMENDED ACTIONS:", "bold");
229 log("1. ✅ System is working correctly - no actions needed", "green");
230 log("2. 💡 Run `npm run dev` to start development server", "blue");
231 log(
232 "3. 📄 Run PDF generation to ensure all versions export correctly",
233 "blue",
234 );
235 log("4. 🔄 Consider setting up these tests in CI/CD pipeline", "blue");
236 } else {
237 log("\n🔧 RECOMMENDED ACTIONS:", "bold");
238 log("1. ❗ Fix the failing tests above", "red");
239 log("2. 🔍 Check file paths and data structure consistency", "yellow");
240 log("3. 🧪 Re-run tests after making changes", "yellow");
241 log("4. 📞 Contact system maintainer if issues persist", "yellow");
242 }
243
244 return allPassed;
245}
246
247// Show usage if help requested
248if (process.argv.includes("--help") || process.argv.includes("-h")) {
249 log("\n📚 CV Test Suite Usage", "bold");
250 log("======================\n");
251 log("Run all tests:");
252 log(" node run-all-tests.mjs", "blue");
253 log("\nRun individual tests:");
254 log(" node test-experience.mjs", "blue");
255 log(" node test-version-integration.mjs", "blue");
256 log(" node validate-experience.mjs", "blue");
257 log("\nOptions:");
258 log(" --help, -h Show this help message", "blue");
259 process.exit(0);
260}
261
262// Run the test suite
263runAllTests()
264 .then((success) => {
265 process.exit(success ? 0 : 1);
266 })
267 .catch((error) => {
268 log(`❌ Unexpected error: ${error.message}`, "red");
269 console.error(error);
270 process.exit(1);
271 });