github.com/evanw/esbuild@v0.21.4/scripts/register-test.js (about) 1 const { installForTests, removeRecursiveSync } = require('./esbuild') 2 const child_process = require('child_process') 3 const path = require('path') 4 const fs = require('fs') 5 const assert = require('assert') 6 const esbuild = installForTests() 7 8 // Create a fresh test directory 9 const rootTestDir = path.join(__dirname, '.register-test') 10 removeRecursiveSync(rootTestDir) 11 fs.mkdirSync(rootTestDir) 12 13 const entry = path.join(rootTestDir, 'entry.ts') 14 fs.writeFileSync(entry, ` 15 console.log('in entry.ts' as string) 16 require('./other.ts') 17 `) 18 19 const other = path.join(rootTestDir, 'other.ts') 20 fs.writeFileSync(other, ` 21 console.log('in other.ts' as string) 22 `) 23 24 const register = path.join(rootTestDir, 'register.js') 25 fs.writeFileSync(register, ` 26 const esbuild = require(${JSON.stringify(esbuild.ESBUILD_PACKAGE_PATH)}); 27 const fs = require('fs'); 28 require.extensions['.ts'] = (mod, filename) => { 29 const ts = fs.readFileSync(filename, 'utf8'); 30 const { code } = esbuild.transformSync(ts, { loader: 'ts' }); 31 mod._compile(code, filename); 32 }; 33 `) 34 35 let tests = { 36 async fromMainThread() { 37 let result = await new Promise((resolve, reject) => child_process.execFile('node', ['-r', register, entry], (err, stdout) => { 38 if (err) reject(err) 39 else resolve(stdout) 40 })) 41 assert.strictEqual(result, `in entry.ts\nin other.ts\n`) 42 }, 43 44 async fromChildThread({ testDir }) { 45 const startThread = path.join(testDir, 'startThread.js') 46 fs.writeFileSync(startThread, ` 47 const worker_threads = require('worker_threads') 48 if (worker_threads.isMainThread) { 49 console.log('in startThread.js') 50 const worker = new worker_threads.Worker(__filename) 51 worker.postMessage(null) 52 worker.on('message', logs => { 53 for (const log of logs) console.log(log) 54 worker.terminate() 55 }) 56 } else { 57 worker_threads.parentPort.on('message', () => { 58 console.log('in worker') 59 let logs = [] 60 console.log = x => logs.push(x) 61 require('../entry.ts') 62 worker_threads.parentPort.postMessage(logs) 63 }) 64 } 65 `) 66 67 let result = await new Promise((resolve, reject) => child_process.execFile('node', ['-r', register, startThread], (err, stdout) => { 68 if (err) reject(err) 69 else resolve(stdout) 70 })) 71 assert.strictEqual(result, `in startThread.js\nin worker\nin entry.ts\nin other.ts\n`) 72 }, 73 } 74 75 async function main() { 76 // Time out these tests after 5 minutes. This exists to help debug test hangs in CI. 77 let minutes = 5 78 let timeout = setTimeout(() => { 79 console.error(`❌ register tests timed out after ${minutes} minutes, exiting...`) 80 process.exit(1) 81 }, minutes * 60 * 1000) 82 83 const runTest = async ([name, fn]) => { 84 let testDir = path.join(rootTestDir, name) 85 try { 86 fs.mkdirSync(testDir) 87 await fn({ esbuild, testDir }) 88 removeRecursiveSync(testDir) 89 return true 90 } catch (e) { 91 console.error(`❌ ${name}: ${e && e.message || e}`) 92 return false 93 } 94 } 95 96 // Run all tests in serial 97 let allTestsPassed = true 98 for (let test of Object.entries(tests)) { 99 if (!await runTest(test)) { 100 allTestsPassed = false 101 } 102 } 103 104 if (!allTestsPassed) { 105 console.error(`❌ register tests failed`) 106 process.exit(1) 107 } else { 108 console.log(`✅ register tests passed`) 109 removeRecursiveSync(rootTestDir) 110 } 111 112 clearTimeout(timeout); 113 } 114 115 main().catch(e => setTimeout(() => { throw e }))