import { describe, expect, jest, test } from "bun:test"; test("error.cause", () => { const err = new Error("error 1"); const err2 = new Error("error 2", { cause: err }); expect( Bun.inspect(err2) .replaceAll("\\", "/") .replaceAll(import.meta.dir.replaceAll("\\", "/"), "[dir]"), ).toMatchInlineSnapshot(` "1 | import { describe, expect, jest, test } from "bun:test"; 2 | 3 | test("error.cause", () => { 4 | const err = new Error("error 1"); 5 | const err2 = new Error("error 2", { cause: err }); ^ error: error 2 at ([dir]/inspect-error.test.js:5:20) 1 | import { describe, expect, jest, test } from "bun:test"; 2 | 3 | test("error.cause", () => { 4 | const err = new Error("error 1"); ^ error: error 1 at ([dir]/inspect-error.test.js:4:19) " `); }); test("Error", () => { const err = new Error("my message"); expect( Bun.inspect(err) .replaceAll("\\", "/") .replaceAll(import.meta.dir.replaceAll("\\", "/"), "[dir]"), ).toMatchInlineSnapshot(` "27 | " 28 | \`); 29 | }); 30 | 31 | test("Error", () => { 32 | const err = new Error("my message"); ^ error: my message at ([dir]/inspect-error.test.js:32:19) " `); }); test("BuildMessage", async () => { try { await import("./inspect-error-fixture-bad.js"); expect.unreachable(); } catch (e) { expect( Bun.inspect(e) .replaceAll("\\", "/") .replaceAll(import.meta.dir.replaceAll("\\", "/"), "[dir]"), ).toMatchInlineSnapshot(` "2 | const duplicateConstDecl = 456; ^ error: "duplicateConstDecl" has already been declared at [dir]/inspect-error-fixture-bad.js:2:7 1 | const duplicateConstDecl = 123; ^ note: "duplicateConstDecl" was originally declared here at [dir]/inspect-error-fixture-bad.js:1:7" `); } }); const normalizeError = str => { // remove debug-only stack trace frames // like "at require (:1:21)" if (str.includes(" (:")) { const splits = str.split("\n"); for (let i = 0; i < splits.length; i++) { if (splits[i].includes(" (:")) { splits.splice(i, 1); i--; } } return splits.join("\n"); } return str; }; test("Error inside minified file (no color) ", () => { try { require("./inspect-error-fixture.min.js"); expect.unreachable(); } catch (e) { expect( normalizeError( Bun.inspect(e, { colors: false }) .replaceAll("\\", "/") .replaceAll(import.meta.dir.replaceAll("\\", "/"), "[dir]") .trim(), ), ).toMatchInlineSnapshot(` "21 | exports.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED=Z; 22 | exports.cache=function(a){return function(){var b=U.current;if(!b)return a.apply(null,arguments);var c=b.getCacheForType(V);b=c.get(a);void 0===b&&(b=W(),c.set(a,b));c=0;for(var f=arguments.length;c ([dir]/inspect-error-fixture.min.js:26:2850) at ([dir]/inspect-error-fixture.min.js:26:2890) at ([dir]/inspect-error.test.js:92:7)" `); } }); test("Error inside minified file (color) ", () => { try { require("./inspect-error-fixture.min.js"); expect.unreachable(); } catch (e) { expect( // TODO: remove this workaround once snapshots work better normalizeError( Bun.stripANSI(Bun.inspect(e, { colors: true })) .replaceAll("\\", "/") .replaceAll(import.meta.dir.replaceAll("\\", "/"), "[dir]") .trim(), ), ).toMatchInlineSnapshot(` "21 | exports.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED=Z; 22 | exports.cache=function(a){return function(){var b=U.current;if(!b)return a.apply(null,arguments);var c=b.getCacheForType(V);b=c.get(a);void 0===b&&(b=W(),c.set(a,b));c=0;for(var f=arguments.length;c ([dir]/inspect-error-fixture.min.js:26:2850) at ([dir]/inspect-error-fixture.min.js:26:2890) at ([dir]/inspect-error.test.js:120:7)" `); } }); test("Inserted originalLine and originalColumn do not appear in node:util.inspect", () => { const err = new Error("my message"); expect( require("util") .inspect(err) .replaceAll("\\", "/") .replaceAll(import.meta.path.replaceAll("\\", "/"), "[file]"), ).toMatchInlineSnapshot(` "Error: my message at ([file]:149:19)" `); }); describe("observable properties", () => { for (let property of ["sourceURL", "line", "column"]) { test(`${property} is observable`, () => { const mock = jest.fn(); const err = new Error("my message"); Object.defineProperty(err, property, { get: mock, enumerable: true, configurable: true, }); expect(mock).not.toHaveBeenCalled(); Bun.inspect(err); expect(mock).not.toHaveBeenCalled(); }); } }); test("error.stack throwing an error doesn't lead to a crash", () => { const err = new Error("my message"); Object.defineProperty(err, "stack", { get: () => { throw new Error("my message"); }, enumerable: true, configurable: true, }); expect(() => { throw err; }).toThrow(); });