From 4b4c37552a25a3a7e8e78d5140ccfa290146235d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20Zugmeyer?= Date: Mon, 9 Sep 2024 20:48:00 +0200 Subject: [PATCH] tests: add tests for local files --- tests/bin.test.ts | 176 ++++++++++++++++++++++++++++++++-------------- 1 file changed, 123 insertions(+), 53 deletions(-) diff --git a/tests/bin.test.ts b/tests/bin.test.ts index 9b2da36..e382729 100644 --- a/tests/bin.test.ts +++ b/tests/bin.test.ts @@ -1,7 +1,8 @@ import { test, afterEach, describe, before, type TestContext } from "node:test"; import { promisify } from "util"; +import path from "path"; import childProcess from "child_process"; -import { readFileSync } from "fs"; +import { readFileSync, writeFileSync, mkdtempSync, rmSync } from "fs"; import http from "http"; import type { AddressInfo } from "net"; @@ -154,6 +155,7 @@ describe("source map retrieval", () => { title: string, { serve, + files, expect: { fetchSourceMaps = true, fetchSourceMapsError = "", @@ -161,7 +163,8 @@ describe("source map retrieval", () => { } = {}, args = [], }: { - serve: MockResponses; + serve?: MockResponses; + files?: Files; expect?: { fetchSourceMaps?: boolean; fetchSourceMapsError?: string; @@ -171,20 +174,30 @@ describe("source map retrieval", () => { }, ) { test(title, async (t: TestContext) => { - const url = await withServer(serve); + let prefix: string; + if (serve) { + prefix = await withServer(serve); + } else if (files) { + prefix = withDirectory(files); + } else { + throw new Error("Either serve or files must be provided"); + } + const statuses = ["Fetching source code..."]; if (fetchSourceMaps) { statuses.push("Fetching source maps..."); } if (fetchSourceMapsError) { - statuses.push(`Failed to fetch source map: ${fetchSourceMapsError}`); + statuses.push( + `Failed to fetch source map: ${fetchSourceMapsError.replaceAll("", prefix)}`, + ); } if (useBeautify) { statuses.push("Beautifying source code..."); } t.assert.deepStrictEqual( - await runBin(`${url}/bundle.min.js:1:64`, ...args), + await runBin(`${prefix}/bundle.min.js:1:64`, ...args), { code: 0, stderr: `${statuses.join("\n")}\n`, @@ -210,66 +223,113 @@ describe("source map retrieval", () => { }); } - testSourceMapRetrieval("use the source map from a sourcemap comment", { - serve: { - "/bundle.min.js": `${generatedCode}\n//# sourceMappingURL=bundle.min.js.map`, - "/bundle.min.js.map": sourceMap, - }, - }); + describe("from an http URL", () => { + testSourceMapRetrieval("use the source map from a sourcemap comment", { + serve: { + "/bundle.min.js": `${generatedCode}\n//# sourceMappingURL=bundle.min.js.map`, + "/bundle.min.js.map": sourceMap, + }, + }); - testSourceMapRetrieval("use the source map from a X-SourceMap header", { - serve: { - "/bundle.min.js": { - body: generatedCode, - headers: { "X-SourceMap": "bundle.min.js.map" }, + testSourceMapRetrieval("use the source map from a X-SourceMap header", { + serve: { + "/bundle.min.js": { + body: generatedCode, + headers: { "X-SourceMap": "bundle.min.js.map" }, + }, + "/bundle.min.js.map": sourceMap, }, - "/bundle.min.js.map": sourceMap, - }, - }); + }); - testSourceMapRetrieval("use the source map from a SourceMap header", { - serve: { - "/bundle.min.js": { - body: generatedCode, - headers: { SourceMap: "bundle.min.js.map" }, + testSourceMapRetrieval("use the source map from a SourceMap header", { + serve: { + "/bundle.min.js": { + body: generatedCode, + headers: { SourceMap: "bundle.min.js.map" }, + }, + "/bundle.min.js.map": sourceMap, }, - "/bundle.min.js.map": sourceMap, - }, - }); + }); - const base64EncodedSourceMap = Buffer.from(sourceMap).toString("base64"); - testSourceMapRetrieval("use the source map from a data-uri", { - serve: { - "/bundle.min.js": `${generatedCode}\n//@ sourceMappingURL=data:application/json;charset=utf-8;base64,${base64EncodedSourceMap}`, - }, - expect: { - fetchSourceMaps: false, - }, - }); + const base64EncodedSourceMap = Buffer.from(sourceMap).toString("base64"); + testSourceMapRetrieval("use the source map from a data-uri", { + serve: { + "/bundle.min.js": `${generatedCode}\n//@ sourceMappingURL=data:application/json;charset=utf-8;base64,${base64EncodedSourceMap}`, + }, + expect: { + fetchSourceMaps: false, + }, + }); - testSourceMapRetrieval( - "fallback to beautify if the source map is not found", - { + testSourceMapRetrieval( + "fallback to beautify if the source map is not found", + { + serve: { + "/bundle.min.js": `${generatedCode}\n//# sourceMappingURL=bundle.min.js.map`, + }, + expect: { + fetchSourceMapsError: "Error: Failed to fetch: Not found", + useBeautify: true, + }, + }, + ); + + testSourceMapRetrieval("no source map option", { serve: { "/bundle.min.js": `${generatedCode}\n//# sourceMappingURL=bundle.min.js.map`, + "/bundle.min.js.map": sourceMap, }, + args: ["--no-source-map"], expect: { - fetchSourceMapsError: "Error: Failed to fetch: Not found", + fetchSourceMaps: false, useBeautify: true, }, - }, - ); + }); + }); - testSourceMapRetrieval("no source map option", { - serve: { - "/bundle.min.js": `${generatedCode}\n//# sourceMappingURL=bundle.min.js.map`, - "/bundle.min.js.map": sourceMap, - }, - args: ["--no-source-map"], - expect: { - fetchSourceMaps: false, - useBeautify: true, - }, + describe("from a local file", () => { + testSourceMapRetrieval("use the source map from a sourcemap comment", { + files: { + "/bundle.min.js": `${generatedCode}\n//# sourceMappingURL=bundle.min.js.map`, + "/bundle.min.js.map": sourceMap, + }, + }); + + const base64EncodedSourceMap = Buffer.from(sourceMap).toString("base64"); + testSourceMapRetrieval("use the source map from a data-uri", { + files: { + "/bundle.min.js": `${generatedCode}\n//@ sourceMappingURL=data:application/json;charset=utf-8;base64,${base64EncodedSourceMap}`, + }, + expect: { + fetchSourceMaps: false, + }, + }); + + testSourceMapRetrieval( + "fallback to beautify if the source map is not found", + { + files: { + "/bundle.min.js": `${generatedCode}\n//# sourceMappingURL=bundle.min.js.map`, + }, + expect: { + fetchSourceMapsError: + "Error: ENOENT: no such file or directory, open '/bundle.min.js.map'", + useBeautify: true, + }, + }, + ); + + testSourceMapRetrieval("no source map option", { + files: { + "/bundle.min.js": `${generatedCode}\n//# sourceMappingURL=bundle.min.js.map`, + "/bundle.min.js.map": sourceMap, + }, + args: ["--no-source-map"], + expect: { + fetchSourceMaps: false, + useBeautify: true, + }, + }); }); }); @@ -330,7 +390,7 @@ type MockResponses = Record< >; function withServer(responses: MockResponses) { - return new Promise((resolve, reject) => { + return new Promise((resolve, reject) => { const server = http.createServer((request, response) => { if (request.url! in responses) { const r = responses[request.url!]; @@ -355,6 +415,16 @@ function withServer(responses: MockResponses) { }); } +type Files = Record; +function withDirectory(files: Files) { + const directory = mkdtempSync("in-situ-test-"); + for (const [name, content] of Object.entries(files)) { + writeFileSync(path.join(directory, name), content); + } + cleanupCallbacks.push(() => rmSync(directory, { recursive: true })); + return directory; +} + function r(template: TemplateStringsArray): string; function r(dedentSize: number): (template: TemplateStringsArray) => string; function r(