waybetter/packages/runtime/tests/devErrors.test.ts

27 lines
1.5 KiB
TypeScript

import assert from 'node:assert/strict';
import test from 'node:test';
import { devErrorLocation, formatDevError } from '../src/devErrors.ts';
test('a start failure is mapped back to the plugin file line (evaluated with a sourceURL)', () => {
// What the host evaluates: one wrapper line, then the file (dev_start_script, START_SCRIPT_LINE_OFFSET = 1).
const file = 'My Plugin.plugin.js';
const source = 'module.exports = class {\n start() {\n null.boom;\n }\n};';
let caught: unknown;
try {
// eslint-disable-next-line no-eval
const Plugin = (0, eval)(`(function(){const module={exports:{}};(function(module){\n${source}\n})(module);return module.exports;})\n//# sourceURL=wb-dev/My%20Plugin.plugin.js`)();
new Plugin().start();
} catch (error) { caught = error; }
assert.ok(caught instanceof TypeError);
const location = devErrorLocation(caught, file);
assert.equal(location.line, 3, 'line 3 of the file, not of the wrapper');
assert.ok(location.column && location.column > 0);
assert.match(formatDevError(location), /^My Plugin\.plugin\.js:3:\d+ — TypeError: /);
});
test('errors without a frame in the file keep the file name and a one-line message', () => {
const location = devErrorLocation('bad\nsecond line', 'a.plugin.js');
assert.deepEqual(location, { file: 'a.plugin.js', line: null, column: null, message: 'bad' });
assert.equal(formatDevError(location), 'a.plugin.js — bad');
assert.equal(devErrorLocation(new Error('x'.repeat(1000)), 'a.plugin.js').message.length, 300);
});