From 10ad6889ce205f860ad088d5f8001e7e1b1190d4 Mon Sep 17 00:00:00 2001 From: Gal Schlezinger Date: Fri, 30 Jun 2023 07:53:02 +0300 Subject: [PATCH] Add a test proxy server so we won't hit Node.js dist so much (#976) --- .gitignore | 1 + e2e/shellcode/script.ts | 1 + jest.config.cjs | 3 ++ jest.global-setup.js | 5 +++ jest.global-teardown.js | 5 +++ tests/proxy-server/index.mjs | 65 ++++++++++++++++++++++++++++++++++++ 6 files changed, 80 insertions(+) create mode 100644 jest.global-setup.js create mode 100644 jest.global-teardown.js create mode 100644 tests/proxy-server/index.mjs diff --git a/.gitignore b/.gitignore index aea3f202b..f72fd21ff 100644 --- a/.gitignore +++ b/.gitignore @@ -7,3 +7,4 @@ feature_tests/.tmp *.log /site/public .vercel +.proxy diff --git a/e2e/shellcode/script.ts b/e2e/shellcode/script.ts index 142f88f8b..2b118d45d 100644 --- a/e2e/shellcode/script.ts +++ b/e2e/shellcode/script.ts @@ -69,6 +69,7 @@ class Script { .filter(Boolean) .join(path.delimiter), FNM_DIR: this.config.fnmDir, + FNM_NODE_DIST_MIRROR: "http://localhost:8080", } delete newProcessEnv.NODE_OPTIONS diff --git a/jest.config.cjs b/jest.config.cjs index 10e45aae7..e15f18a21 100644 --- a/jest.config.cjs +++ b/jest.config.cjs @@ -1,9 +1,12 @@ /** @type {import('ts-jest').JestConfigWithTsJest} */ module.exports = { preset: "ts-jest/presets/default-esm", + globalSetup: "./jest.global-setup.js", + globalTeardown: "./jest.global-teardown.js", testEnvironment: "node", testTimeout: 120000, extensionsToTreatAsEsm: [".ts"], + testPathIgnorePatterns: ["/node_modules/", "/dist/", "/target/"], moduleNameMapper: { "^(\\.{1,2}/.*)\\.js$": "$1", "#ansi-styles": "ansi-styles/index.js", diff --git a/jest.global-setup.js b/jest.global-setup.js new file mode 100644 index 000000000..7c52a6be1 --- /dev/null +++ b/jest.global-setup.js @@ -0,0 +1,5 @@ +import { server } from "./tests/proxy-server/index.mjs" + +export default function () { + server.listen(8080) +} diff --git a/jest.global-teardown.js b/jest.global-teardown.js new file mode 100644 index 000000000..d16c255d9 --- /dev/null +++ b/jest.global-teardown.js @@ -0,0 +1,5 @@ +import { server } from "./tests/proxy-server/index.mjs" + +export default () => { + server.close() +} diff --git a/tests/proxy-server/index.mjs b/tests/proxy-server/index.mjs new file mode 100644 index 000000000..b306a6f7f --- /dev/null +++ b/tests/proxy-server/index.mjs @@ -0,0 +1,65 @@ +// @ts-check + +import { createServer } from "node:http" +import path from "node:path" +import fs from "node:fs" +import crypto from "node:crypto" +import fetch from "node-fetch" +import chalk from "chalk" + +const baseDir = path.join(process.cwd(), ".proxy") +try { + fs.mkdirSync(baseDir, { recursive: true }) +} catch (e) {} + +/** @type {Map, body: ArrayBuffer }>>} */ +const cache = new Map() + +export const server = createServer((req, res) => { + const pathname = req.url ?? "/" + const hash = crypto + .createHash("sha1") + .update(pathname ?? "/") + .digest("hex") + const extension = path.extname(pathname) + const filename = path.join(baseDir, hash) + extension + const headersFilename = path.join(baseDir, hash) + ".headers.json" + try { + const headers = JSON.parse(fs.readFileSync(headersFilename, "utf-8")) + const body = fs.createReadStream(filename) + console.log(chalk.green.dim(`[proxy] hit: ${pathname} -> ${filename}`)) + res.writeHead(200, headers) + body.pipe(res) + } catch { + let promise = cache.get(filename) + if (!promise) { + console.log(chalk.red.dim(`[proxy] miss: ${pathname} -> ${filename}`)) + promise = fetch( + "https://nodejs.org/dist/" + pathname.replace(/^\/+/, ""), + { + compress: false, + } + ).then(async (response) => { + const headers = Object.fromEntries(response.headers.entries()) + const body = await response.arrayBuffer() + fs.writeFileSync(headersFilename, JSON.stringify(headers)) + fs.writeFileSync(filename, Buffer.from(body)) + return { headers, body } + }) + cache.set(filename, promise) + promise.finally(() => cache.delete(filename)) + } + + promise.then( + ({ headers, body }) => { + res.writeHead(200, headers) + res.end(Buffer.from(body)) + }, + (err) => { + console.error(err) + res.writeHead(500) + res.end() + } + ) + } +})