1import * as common from '../common/index.mjs'; 2import * as fixtures from '../common/fixtures.mjs'; 3import * as snapshot from '../common/assertSnapshot.js'; 4import * as os from 'node:os'; 5import { describe, it } from 'node:test'; 6import { pathToFileURL } from 'node:url'; 7 8const skipForceColors = 9 process.config.variables.icu_gyp_path !== 'tools/icu/icu-generic.gyp' || 10 process.config.variables.node_shared_openssl || 11 (common.isWindows && (Number(os.release().split('.')[0]) !== 10 || Number(os.release().split('.')[2]) < 14393)); // See https://github.com/nodejs/node/pull/33132 12 13 14function replaceStackTrace(str) { 15 return snapshot.replaceStackTrace(str, '$1at *$7\n'); 16} 17 18function replaceForceColorsStackTrace(str) { 19 // eslint-disable-next-line no-control-regex 20 return str.replaceAll(/(\[90m\W+)at .*node:.*/g, '$1at *[39m'); 21} 22 23describe('errors output', { concurrency: true }, () => { 24 function normalize(str) { 25 return str.replaceAll(snapshot.replaceWindowsPaths(process.cwd()), '') 26 .replaceAll(pathToFileURL(process.cwd()).pathname, '') 27 .replaceAll('//', '*') 28 .replaceAll(/\/(\w)/g, '*$1') 29 .replaceAll('*test*', '*') 30 .replaceAll('*fixtures*errors*', '*') 31 .replaceAll('file:**', 'file:*/'); 32 } 33 34 function normalizeNoNumbers(str) { 35 return normalize(str).replaceAll(/\d+:\d+/g, '*:*').replaceAll(/:\d+/g, ':*').replaceAll('*fixtures*message*', '*'); 36 } 37 const common = snapshot 38 .transform(snapshot.replaceWindowsLineEndings, snapshot.replaceWindowsPaths); 39 const defaultTransform = snapshot.transform(common, normalize, snapshot.replaceNodeVersion); 40 const errTransform = snapshot.transform(common, normalizeNoNumbers, snapshot.replaceNodeVersion); 41 const promiseTransform = snapshot.transform(common, replaceStackTrace, 42 normalizeNoNumbers, snapshot.replaceNodeVersion); 43 const forceColorsTransform = snapshot.transform(common, normalize, 44 replaceForceColorsStackTrace, snapshot.replaceNodeVersion); 45 46 const tests = [ 47 { name: 'errors/async_error_eval_cjs.js' }, 48 { name: 'errors/async_error_eval_esm.js' }, 49 { name: 'errors/async_error_microtask_main.js' }, 50 { name: 'errors/async_error_nexttick_main.js' }, 51 { name: 'errors/async_error_sync_main.js' }, 52 { name: 'errors/async_error_sync_esm.mjs' }, 53 { name: 'errors/error_aggregateTwoErrors.js', transform: errTransform }, 54 { name: 'errors/error_exit.js', transform: errTransform }, 55 { name: 'errors/error_with_nul.js', transform: errTransform }, 56 { name: 'errors/events_unhandled_error_common_trace.js', transform: errTransform }, 57 { name: 'errors/events_unhandled_error_nexttick.js', transform: errTransform }, 58 { name: 'errors/events_unhandled_error_sameline.js', transform: errTransform }, 59 { name: 'errors/events_unhandled_error_subclass.js', transform: errTransform }, 60 { name: 'errors/throw_custom_error.js', transform: errTransform }, 61 { name: 'errors/throw_in_line_with_tabs.js', transform: errTransform }, 62 { name: 'errors/throw_non_error.js', transform: errTransform }, 63 { name: 'errors/promise_always_throw_unhandled.js', transform: promiseTransform }, 64 { skip: skipForceColors, name: 'errors/force_colors.js', 65 transform: forceColorsTransform, env: { FORCE_COLOR: 1 } }, 66 ]; 67 for (const { name, transform = defaultTransform, env, skip = false } of tests) { 68 it(name, { skip }, async () => { 69 await snapshot.spawnAndAssert(fixtures.path(name), transform, { env }); 70 }); 71 } 72}); 73