From 9d0891f2635459864641f7c5d7c177124cec6ff8 Mon Sep 17 00:00:00 2001 From: Evan Wallace Date: Thu, 12 Jan 2023 14:59:01 -0500 Subject: [PATCH] additional tests --- CHANGELOG.md | 5 +-- scripts/js-api-tests.js | 88 ++++++++++++++++++++++++++++++++++++++++ scripts/ts-type-tests.js | 35 +++++++++++++--- 3 files changed, 119 insertions(+), 9 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ead03df5a01..683e3778d17 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -58,8 +58,7 @@ At a high level, the breaking changes in this release fix some long-standing iss } ``` - This JSON should also enable more complex live reloading scenarios. - For example, the following code hot-swaps changed CSS `` tags in place without reloading the page (but still reloads when there are other types of changes): + This JSON should also enable more complex live reloading scenarios. For example, the following code hot-swaps changed CSS `` tags in place without reloading the page (but still reloads when there are other types of changes): ```js new EventSource('/esbuild').addEventListener('change', e => { @@ -126,7 +125,7 @@ At a high level, the breaking changes in this release fix some long-standing iss ``` > Local: http://127.0.0.1:8000/ - > Network: http://192.168.1.1:8000/ + > Network: http://192.168.0.1:8000/ ``` The CLI still does this, but now the JS and Go serve mode APIs will do this too. This only happens when the log level is set to `verbose`, `debug`, or `info` but not when it's set to `warning`, `error`, or `silent`. diff --git a/scripts/js-api-tests.js b/scripts/js-api-tests.js index 66bd78ad9e4..417a788d122 100644 --- a/scripts/js-api-tests.js +++ b/scripts/js-api-tests.js @@ -3,6 +3,7 @@ const child_process = require('child_process') const assert = require('assert') const path = require('path') const http = require('http') +const https = require('https') const fs = require('fs') const vm = require('vm') @@ -3424,6 +3425,32 @@ function fetch(host, port, path, headers) { }) } +function fetchHTTPS(host, port, path, { certfile }) { + return new Promise((resolve, reject) => { + const checkServerIdentity = (hostname, cert) => { + // I'm not sure why node seems to always reject the host "127.0.0.1" + assert.strictEqual(hostname, '127.0.0.1') + assert.strictEqual(cert.subject.CN, '127.0.0.1') + } + const ca = [fs.readFileSync(certfile, 'utf8')] + https.get({ host, port, path, ca, checkServerIdentity }, res => { + const chunks = [] + res.on('data', chunk => chunks.push(chunk)) + res.on('end', () => { + const content = Buffer.concat(chunks) + if (res.statusCode < 200 || res.statusCode > 299) { + const error = new Error(`${res.statusCode} when fetching ${path}: ${content}`) + error.statusCode = res.statusCode + reject(error) + } else { + content.headers = res.headers + resolve(content) + } + }) + }).on('error', reject) + }) +} + const makeRebuildUntilPlugin = () => { let onEnd @@ -3796,6 +3823,67 @@ let serveTests = { } }, + async serveBasicHTTPS({ esbuild, testDir }) { + const run = command => new Promise((resolve, reject) => { + child_process.execFile(command.shift(), command, (error, stdout, stderr) => { + if (error) reject(error) + else resolve() + }) + }) + + try { + await run(['which', 'openssl']) + } catch { + console.warn('Skipping HTTPS tests because the "openssl" command was not found') + return + } + + const keyfile = path.join(testDir, 'key.pem') + const certfile = path.join(testDir, 'cert.pem') + const requestFile = path.join(testDir, 'csr.pem') + await run(['openssl', 'genrsa', '-out', keyfile]) + await run(['openssl', 'req', '-new', '-key', keyfile, '-out', requestFile, '-subj', '/CN=127.0.0.1']) + await run(['openssl', 'x509', '-req', '-days', '9999', '-in', requestFile, '-signkey', keyfile, '-out', certfile]) + + const input = path.join(testDir, 'in.js') + await writeFileAsync(input, `console.log(123)`) + + let onRequest; + let singleRequestPromise = new Promise(resolve => { + onRequest = resolve; + }); + + const context = await esbuild.context({ + entryPoints: [input], + format: 'esm', + outdir: testDir, + write: false, + }); + try { + const result = await context.serve({ + host: '127.0.0.1', + keyfile, + certfile, + onRequest, + }) + assert.strictEqual(result.host, '127.0.0.1'); + assert.strictEqual(typeof result.port, 'number'); + + const buffer = await fetchHTTPS(result.host, result.port, '/in.js', { certfile }) + assert.strictEqual(buffer.toString(), `console.log(123);\n`); + assert.strictEqual(fs.readFileSync(input, 'utf8'), `console.log(123)`) + + let singleRequest = await singleRequestPromise; + assert.strictEqual(singleRequest.method, 'GET'); + assert.strictEqual(singleRequest.path, '/in.js'); + assert.strictEqual(singleRequest.status, 200); + assert.strictEqual(typeof singleRequest.remoteAddress, 'string'); + assert.strictEqual(typeof singleRequest.timeInMS, 'number'); + } finally { + await context.dispose(); + } + }, + async serveOutfile({ esbuild, testDir }) { const input = path.join(testDir, 'in.js') await writeFileAsync(input, `console.log(123)`) diff --git a/scripts/ts-type-tests.js b/scripts/ts-type-tests.js index 51ca13d5755..30b94a8d194 100644 --- a/scripts/ts-type-tests.js +++ b/scripts/ts-type-tests.js @@ -37,22 +37,45 @@ const tests = { esbuild.transform('') esbuild.transform('', {}) `, + mangleCache: ` import * as esbuild from 'esbuild' esbuild.buildSync({ mangleCache: {} }).mangleCache['x'] - esbuild.build({ mangleCache: {} }).then(result => result.mangleCache['x']) + esbuild.build({ mangleCache: {} }) + .then(result => result.mangleCache['x']) `, writeFalseOutputFiles: ` import * as esbuild from 'esbuild' esbuild.buildSync({ write: false }).outputFiles[0] - esbuild.build({ write: false }).then(result => result.outputFiles[0]) + esbuild.build({ write: false }) + .then(result => result.outputFiles[0]) `, metafileTrue: ` - import {build, analyzeMetafile} from 'esbuild'; - build({ metafile: true }).then(result => { - analyzeMetafile(result.metafile) - }) + import {build, buildSync, analyzeMetafile} from 'esbuild'; + analyzeMetafile(buildSync({ metafile: true }).metafile) + build({ metafile: true }) + .then(result => analyzeMetafile(result.metafile)) + `, + + contextMangleCache: ` + import * as esbuild from 'esbuild' + esbuild.context({ mangleCache: {} }) + .then(context => context.rebuild()) + .then(result => result.mangleCache['x']) `, + contextWriteFalseOutputFiles: ` + import * as esbuild from 'esbuild' + esbuild.context({ write: false }) + .then(context => context.rebuild()) + .then(result => result.outputFiles[0]) + `, + contextMetafileTrue: ` + import {context, analyzeMetafile} from 'esbuild'; + context({ metafile: true }) + .then(context => context.rebuild()) + .then(result => analyzeMetafile(result.metafile)) + `, + allOptionsTransform: ` export {} import {transform} from 'esbuild'