From ca2b1e9dec929aedc2079a09673df38ddb469394 Mon Sep 17 00:00:00 2001 From: Garry Tan Date: Thu, 16 Apr 2026 13:35:41 -0700 Subject: [PATCH] test(browse): add build validation test for server-node.mjs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Two assertions: 1. `node --check` passes on the built `server-node.mjs` (valid ES module syntax). This catches regressions where the post-processing steps (perl regex replacements) corrupt the bundle. 2. No inlined `@ngrok/ngrok` module identifiers (ngrok_napi, platform- specific binding packages). Verifies the --external flag actually kept it external. Skips gracefully when `browse/dist/server-node.mjs` is missing — the dist dir is gitignored, so a fresh clone + `bun test` without a prior build is a valid state, not a failure. Co-Authored-By: Claude Opus 4.7 (1M context) --- browse/test/build.test.ts | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 browse/test/build.test.ts diff --git a/browse/test/build.test.ts b/browse/test/build.test.ts new file mode 100644 index 00000000..050f3576 --- /dev/null +++ b/browse/test/build.test.ts @@ -0,0 +1,28 @@ +import { describe, test, expect } from 'bun:test'; +import { execSync } from 'child_process'; +import * as fs from 'fs'; +import * as path from 'path'; + +const DIST_DIR = path.resolve(__dirname, '..', 'dist'); +const SERVER_NODE = path.join(DIST_DIR, 'server-node.mjs'); + +describe('build: server-node.mjs', () => { + test('passes node --check if present', () => { + if (!fs.existsSync(SERVER_NODE)) { + // browse/dist is gitignored; no build has run in this checkout. + // Skip rather than fail so plain `bun test` without a prior build passes. + return; + } + expect(() => execSync(`node --check ${SERVER_NODE}`, { stdio: 'pipe' })).not.toThrow(); + }); + + test('does not inline @ngrok/ngrok (must be external)', () => { + if (!fs.existsSync(SERVER_NODE)) return; + const bundle = fs.readFileSync(SERVER_NODE, 'utf-8'); + // Dynamic imports of externalized packages show up as string literals in the bundle, + // not as inlined module code. The heuristic: ngrok's native binding loader would + // reference its own internals. If any ngrok internal identifier appears, the module + // got inlined despite the --external flag. + expect(bundle).not.toMatch(/ngrok_napi|ngrokNapi|@ngrok\/ngrok-darwin|@ngrok\/ngrok-linux|@ngrok\/ngrok-win32/); + }); +});