atk / solid-register

MIT License
18 stars 1 forks source link

Crazy error messages in 0.1.1 while testing in uvu #3

Closed thetarnav closed 2 years ago

thetarnav commented 2 years ago

We've updated to 0.1.1 from 0.0.18 on solid-primitives, and this is what happens when some of the test fail:

https://user-images.githubusercontent.com/24491503/147964486-8d85ac0b-a293-44f0-9654-baca998e53db.mp4

This is some error that was small enough to copy:
``` test\eventListener.test.ts createEventListener ✘ (0 / 1) FAIL createEventListener "..." Expected values to be strictly equal: (is) ++false (Expected) --true (Actual) at assert (const { dequal } = require('dequal'); const { compare, lines } = require('uvu/diff'); function dedent(str) { str = str.replace(//r?/n/g, '/n'); let arr = str.match(/^[ /t]*(?=/S)/gm); let i = 0, min = 1/0, len = (arr||[]).length; for (; i < len; i++) min = Math.min(min, arr[i].length); return len && min ? str.replace(new RegExp(`^[ //t]{${min}}`, 'gm'), '') : str; } class Assertion extends Error { constructor(opts={}) { super(opts.message); this.name = 'Assertion'; this.code = 'ERR_ASSERTION'; if (Error.captureStackTrace) { Error.captureStackTrace(this, this.constructor); } this.details = opts.details || false; this.generated = !!opts.generated; this.operator = opts.operator; this.expects = opts.expects; this.actual = opts.actual; } } function assert(bool, actual, expects, operator, detailer, backup, msg) { if (bool) return; let message = msg || backup; if (msg instanceof Error) throw msg; let details = detailer && detailer(actual, expects); throw new Assertion({ actual, expects, operator, message, details, generated: !msg }); } function ok(val, msg) { assert(!!val, false, true, 'ok', false, 'Expected value to be truthy', msg); } function is(val, exp, msg) { assert(val === exp, val, exp, 'is', compare, 'Expected values to be strictly equal:', msg); } function equal(val, exp, msg) { assert(dequal(val, exp), val, exp, 'equal', compare, 'Expected values to be deeply equal:', msg); } function unreachable(msg) { assert(false, true, false, 'unreachable', false, 'Expected not to be reached!', msg); } function type(val, exp, msg) { let tmp = typeof val; assert(tmp === exp, tmp, exp, 'type', false, `Expected "${tmp}" to be "${exp}"`, msg); } function instance(val, exp, msg) { let name = '`' + (exp.name || exp.constructor.name) + '`'; assert(val instanceof exp, val, exp, 'instance', false, `Expected value to be an instance of ${name}`, msg); } function match(val, exp, msg) { if (typeof exp === 'string') { assert(val.includes(exp), val, exp, 'match', false, `Expected value to include "${exp}" substring`, msg); } else { assert(exp.test(val), val, exp, 'match', false, `Expected value to match /`${String(exp)}/` pattern`, msg); } } function snapshot(val, exp, msg) { val=dedent(val); exp=dedent(exp); assert(val === exp, val, exp, 'snapshot', lines, 'Expected value to match snapshot:', msg); } const lineNums = (x, y) => lines(x, y, 1); function fixture(val, exp, msg) { val=dedent(val); exp=dedent(exp); assert(val === exp, val, exp, 'fixture', lineNums, 'Expected value to match fixture:', msg); } function throws(blk, exp, msg) { if (!msg && typeof exp === 'string') { msg = exp; exp = null; } try { blk(); assert(false, false, true, 'throws', false, 'Expected function to throw', msg); } catch (err) { if (err instanceof Assertion) throw err; if (typeof exp === 'function') { assert(exp(err), false, true, 'throws', false, 'Expected function to throw matching exception', msg); } else if (exp instanceof RegExp) { assert(exp.test(err.message), false, true, 'throws', false, `Expected function to throw exception matching /`${String(exp)}/` pattern`, msg); } } } // --- function not(val, msg) { assert(!val, true, false, 'not', false, 'Expected value to be falsey', msg); } not.ok = not; is.not = function (val, exp, msg) { assert(val !== exp, val, exp, 'is.not', false, 'Expected values not to be strictly equal', msg); } not.equal = function (val, exp, msg) { assert(!dequal(val, exp), val, exp, 'not.equal', false, 'Expected values not to be deeply equal', msg); } not.type = function (val, exp, msg) { let tmp = typeof val; assert(tmp !== exp, tmp, exp, 'not.type', false, `Expected "${tmp}" not to be "${exp}"`, msg); } not.instance = function (val, exp, msg) { let name = '`' + (exp.name || exp.constructor.name) + '`'; assert(!(val instanceof exp), val, exp, 'not.instance', false, `Expected value not to be an instance of ${name}`, msg); } not.snapshot = function (val, exp, msg) { val=dedent(val); exp=dedent(exp); assert(val !== exp, val, exp, 'not.snapshot', false, 'Expected value not to match snapshot', msg); } not.fixture = function (val, exp, msg) { val=dedent(val); exp=dedent(exp); assert(val !== exp, val, exp, 'not.fixture', false, 'Expected value not to match fixture', msg); } not.match = function (val, exp, msg) { if (typeof exp === 'string') { assert(!val.includes(exp), val, exp, 'not.match', false, `Expected value not to include "${exp}" substring`, msg); } else { assert(!exp.test(val), val, exp, 'not.match', false, `Expected value not to match /`${String(exp)}/` pattern`, msg); } } not.throws = function (blk, exp, msg) { if (!msg && typeof exp === 'string') { msg = exp; exp = null; } try { blk(); } catch (err) { if (typeof exp === 'function') { assert(!exp(err), true, false, 'not.throws', false, 'Expected function not to throw matching exception', msg); } else if (exp instanceof RegExp) { assert(!exp.test(err.message), true, false, 'not.throws', false, `Expected function not to throw exception matching /`${String(exp)}/` pattern`, msg); } else if (!exp) { assert(false, true, false, 'not.throws', false, 'Expected function not to throw', msg); } } } exports.Assertion = Assertion; exports.equal = equal; exports.fixture = fixture; exports.instance = instance; exports.is = is; exports.match = match; exports.not = not; exports.ok = ok; exports.snapshot = snapshot; exports.throws = throws; exports.type = type; exports.unreachable = unreachable;:33:9) at Object.is (const { dequal } = require('dequal'); const { compare, lines } = require('uvu/diff'); function dedent(str) { str = str.replace(//r?/n/g, '/n'); let arr = str.match(/^[ /t]*(?=/S)/gm); let i = 0, min = 1/0, len = (arr||[]).length; for (; i < len; i++) min = Math.min(min, arr[i].length); return len && min ? str.replace(new RegExp(`^[ //t]{${min}}`, 'gm'), '') : str; } class Assertion extends Error { constructor(opts={}) { super(opts.message); this.name = 'Assertion'; this.code = 'ERR_ASSERTION'; if (Error.captureStackTrace) { Error.captureStackTrace(this, this.constructor); } this.details = opts.details || false; this.generated = !!opts.generated; this.operator = opts.operator; this.expects = opts.expects; this.actual = opts.actual; } } function assert(bool, actual, expects, operator, detailer, backup, msg) { if (bool) return; let message = msg || backup; if (msg instanceof Error) throw msg; let details = detailer && detailer(actual, expects); throw new Assertion({ actual, expects, operator, message, details, generated: !msg }); } function ok(val, msg) { assert(!!val, false, true, 'ok', false, 'Expected value to be truthy', msg); } function is(val, exp, msg) { assert(val === exp, val, exp, 'is', compare, 'Expected values to be strictly equal:', msg); } function equal(val, exp, msg) { assert(dequal(val, exp), val, exp, 'equal', compare, 'Expected values to be deeply equal:', msg); } function unreachable(msg) { assert(false, true, false, 'unreachable', false, 'Expected not to be reached!', msg); } function type(val, exp, msg) { let tmp = typeof val; assert(tmp === exp, tmp, exp, 'type', false, `Expected "${tmp}" to be "${exp}"`, msg); } function instance(val, exp, msg) { let name = '`' + (exp.name || exp.constructor.name) + '`'; assert(val instanceof exp, val, exp, 'instance', false, `Expected value to be an instance of ${name}`, msg); } function match(val, exp, msg) { if (typeof exp === 'string') { assert(val.includes(exp), val, exp, 'match', false, `Expected value to include "${exp}" substring`, msg); } else { assert(exp.test(val), val, exp, 'match', false, `Expected value to match /`${String(exp)}/` pattern`, msg); } } function snapshot(val, exp, msg) { val=dedent(val); exp=dedent(exp); assert(val === exp, val, exp, 'snapshot', lines, 'Expected value to match snapshot:', msg); } const lineNums = (x, y) => lines(x, y, 1); function fixture(val, exp, msg) { val=dedent(val); exp=dedent(exp); assert(val === exp, val, exp, 'fixture', lineNums, 'Expected value to match fixture:', msg); } function throws(blk, exp, msg) { if (!msg && typeof exp === 'string') { msg = exp; exp = null; } try { blk(); assert(false, false, true, 'throws', false, 'Expected function to throw', msg); } catch (err) { if (err instanceof Assertion) throw err; if (typeof exp === 'function') { assert(exp(err), false, true, 'throws', false, 'Expected function to throw matching exception', msg); } else if (exp instanceof RegExp) { assert(exp.test(err.message), false, true, 'throws', false, `Expected function to throw exception matching /`${String(exp)}/` pattern`, msg); } } } // --- function not(val, msg) { assert(!val, true, false, 'not', false, 'Expected value to be falsey', msg); } not.ok = not; is.not = function (val, exp, msg) { assert(val !== exp, val, exp, 'is.not', false, 'Expected values not to be strictly equal', msg); } not.equal = function (val, exp, msg) { assert(!dequal(val, exp), val, exp, 'not.equal', false, 'Expected values not to be deeply equal', msg); } not.type = function (val, exp, msg) { let tmp = typeof val; assert(tmp !== exp, tmp, exp, 'not.type', false, `Expected "${tmp}" not to be "${exp}"`, msg); } not.instance = function (val, exp, msg) { let name = '`' + (exp.name || exp.constructor.name) + '`'; assert(!(val instanceof exp), val, exp, 'not.instance', false, `Expected value not to be an instance of ${name}`, msg); } not.snapshot = function (val, exp, msg) { val=dedent(val); exp=dedent(exp); assert(val !== exp, val, exp, 'not.snapshot', false, 'Expected value not to match snapshot', msg); } not.fixture = function (val, exp, msg) { val=dedent(val); exp=dedent(exp); assert(val !== exp, val, exp, 'not.fixture', false, 'Expected value not to match fixture', msg); } not.match = function (val, exp, msg) { if (typeof exp === 'string') { assert(!val.includes(exp), val, exp, 'not.match', false, `Expected value not to include "${exp}" substring`, msg); } else { assert(!exp.test(val), val, exp, 'not.match', false, `Expected value not to match /`${String(exp)}/` pattern`, msg); } } not.throws = function (blk, exp, msg) { if (!msg && typeof exp === 'string') { msg = exp; exp = null; } try { blk(); } catch (err) { if (typeof exp === 'function') { assert(!exp(err), true, false, 'not.throws', false, 'Expected function not to throw matching exception', msg); } else if (exp instanceof RegExp) { assert(!exp.test(err.message), true, false, 'not.throws', false, `Expected function not to throw exception matching /`${String(exp)}/` pattern`, msg); } else if (!exp) { assert(false, true, false, 'not.throws', false, 'Expected function not to throw', msg); } } } exports.Assertion = Assertion; exports.equal = equal; exports.fixture = fixture; exports.instance = instance; exports.is = is; exports.match = match; exports.not = not; exports.ok = ok; exports.snapshot = snapshot; exports.throws = throws; exports.type = type; exports.unreachable = unreachable;:39:3) at Object.handler (import { suite } from "uvu"; import * as assert from "uvu/assert"; const test = suite("createEventListener"); test("...", () => { assert.is(true, false); }); test.run(); :23:10) at Number.runner (const kleur = require('kleur'); const { compare } = require('uvu/diff'); let isCLI = false, isNode = false; let hrtime = (now = Date.now()) => () => (Date.now() - now).toFixed(2) + 'ms'; let write = console.log; const into = (ctx, key) => (name, handler) => ctx[key].push({ name, handler }); const context = (state) => ({ tests:[], before:[], after:[], bEach:[], aEach:[], only:[], skips:0, state }); const milli = arr => (arr[0]*1e3 + arr[1]/1e6).toFixed(2) + 'ms'; const hook = (ctx, key) => handler => ctx[key].push(handler); if (isNode = typeof process < 'u' && typeof process.stdout < 'u') { // globalThis polyfill; Node < 12 if (typeof globalThis !== 'object') { Object.defineProperty(global, 'globalThis', { get: function () { return this } }); } let rgx = /(/.bin[//+//]uvu$|uvu[//+//]bin/.js)/i; isCLI = process.argv.some(x => rgx.test(x)); // attach node-specific utils write = x => process.stdout.write(x); hrtime = (now = process.hrtime()) => () => milli(process.hrtime(now)); } else if (typeof performance < 'u') { hrtime = (now = performance.now()) => () => (performance.now() - now).toFixed(2) + 'ms'; } globalThis.UVU_QUEUE = globalThis.UVU_QUEUE || []; isCLI || UVU_QUEUE.push([null]); const QUOTE = kleur.dim('"'), GUTTER = '/n '; const FAIL = kleur.red('✘ '), PASS = kleur.gray('• '); const IGNORE = /^/s*at.*(?:/(|/s)(?:node|(internal//[/w/]*))/; const FAILURE = kleur.bold().bgRed(' FAIL '); const FILE = kleur.bold().underline().white; const SUITE = kleur.bgWhite().bold; function stack(stack, idx) { let i=0, line, out=''; let arr = stack.substring(idx).replace(////g, '/').split('/n'); for (; i < arr.length; i++) { line = arr[i].trim(); if (line.length && !IGNORE.test(line)) { out += '/n ' + line; } } return kleur.grey(out) + '/n'; } function format(name, err, suite = '') { let { details, operator='' } = err; let idx = err.stack && err.stack.indexOf('/n'); if (err.name.startsWith('AssertionError') && !operator.includes('not')) details = compare(err.actual, err.expected); // TODO? let str = ' ' + FAILURE + (suite ? kleur.red(SUITE(` ${suite} `)) : '') + ' ' + QUOTE + kleur.red().bold(name) + QUOTE; str += '/n ' + err.message + (operator ? kleur.italic().dim(` (${operator})`) : '') + '/n'; if (details) str += GUTTER + details.split('/n').join(GUTTER); if (!!~idx) str += stack(err.stack, idx); return str + '/n'; } async function runner(ctx, name) { let { only, tests, before, after, bEach, aEach, state } = ctx; let hook, test, arr = only.length ? only : tests; let num=0, errors='', total=arr.length; try { if (name) write(SUITE(kleur.black(` ${name} `)) + ' '); for (hook of before) await hook(state); for (test of arr) { state.__test__ = test.name; try { for (hook of bEach) await hook(state); await test.handler(state); for (hook of aEach) await hook(state); write(PASS); num++; } catch (err) { for (hook of aEach) await hook(state); if (errors.length) errors += '/n'; errors += format(test.name, err, name); write(FAIL); } } } finally { state.__test__ = ''; for (hook of after) await hook(state); let msg = ` (${num} / ${total})/n`; let skipped = (only.length ? tests.length : 0) + ctx.skips; write(errors.length ? kleur.red(msg) : kleur.green(msg)); return [errors || true, num, skipped, total]; } } let timer; function defer() { clearTimeout(timer); timer = setTimeout(exec); } function setup(ctx, name = '') { ctx.state.__test__ = ''; ctx.state.__suite__ = name; const test = into(ctx, 'tests'); test.before = hook(ctx, 'before'); test.before.each = hook(ctx, 'bEach'); test.after = hook(ctx, 'after'); test.after.each = hook(ctx, 'aEach'); test.only = into(ctx, 'only'); test.skip = () => { ctx.skips++ }; test.run = () => { let copy = { ...ctx }; let run = runner.bind(0, copy, name); Object.assign(ctx, context(copy.state)); UVU_QUEUE[globalThis.UVU_INDEX || 0].push(run); isCLI || defer(); }; return test; } const suite = (name = '', state = {}) => setup(context(state), name); const test = suite(); async function exec(bail) { let timer = hrtime(); let done=0, total=0, skips=0, code=0; for (let group of UVU_QUEUE) { if (total) write('/n'); let name = group.shift(); if (name != null) write(FILE(name) + '/n'); for (let test of group) { let [errs, ran, skip, max] = await test(); total += max; done += ran; skips += skip; if (errs.length) { write('/n' + errs + '/n'); code=1; if (bail) return isNode && process.exit(1); } } } write('/n Total: ' + total); write((code ? kleur.red : kleur.green)('/n Passed: ' + done)); write('/n Skipped: ' + (skips ? kleur.yellow(skips) : skips)); write('/n Duration: ' + timer() + '/n/n'); if (isNode) process.exitCode = code; } exports.exec = exec; exports.suite = suite; exports.test = test;:87:21) at exec (const kleur = require('kleur'); const { compare } = require('uvu/diff'); let isCLI = false, isNode = false; let hrtime = (now = Date.now()) => () => (Date.now() - now).toFixed(2) + 'ms'; let write = console.log; const into = (ctx, key) => (name, handler) => ctx[key].push({ name, handler }); const context = (state) => ({ tests:[], before:[], after:[], bEach:[], aEach:[], only:[], skips:0, state }); const milli = arr => (arr[0]*1e3 + arr[1]/1e6).toFixed(2) + 'ms'; const hook = (ctx, key) => handler => ctx[key].push(handler); if (isNode = typeof process < 'u' && typeof process.stdout < 'u') { // globalThis polyfill; Node < 12 if (typeof globalThis !== 'object') { Object.defineProperty(global, 'globalThis', { get: function () { return this } }); } let rgx = /(/.bin[//+//]uvu$|uvu[//+//]bin/.js)/i; isCLI = process.argv.some(x => rgx.test(x)); // attach node-specific utils write = x => process.stdout.write(x); hrtime = (now = process.hrtime()) => () => milli(process.hrtime(now)); } else if (typeof performance < 'u') { hrtime = (now = performance.now()) => () => (performance.now() - now).toFixed(2) + 'ms'; } globalThis.UVU_QUEUE = globalThis.UVU_QUEUE || []; isCLI || UVU_QUEUE.push([null]); const QUOTE = kleur.dim('"'), GUTTER = '/n '; const FAIL = kleur.red('✘ '), PASS = kleur.gray('• '); const IGNORE = /^/s*at.*(?:/(|/s)(?:node|(internal//[/w/]*))/; const FAILURE = kleur.bold().bgRed(' FAIL '); const FILE = kleur.bold().underline().white; const SUITE = kleur.bgWhite().bold; function stack(stack, idx) { let i=0, line, out=''; let arr = stack.substring(idx).replace(////g, '/').split('/n'); for (; i < arr.length; i++) { line = arr[i].trim(); if (line.length && !IGNORE.test(line)) { out += '/n ' + line; } } return kleur.grey(out) + '/n'; } function format(name, err, suite = '') { let { details, operator='' } = err; let idx = err.stack && err.stack.indexOf('/n'); if (err.name.startsWith('AssertionError') && !operator.includes('not')) details = compare(err.actual, err.expected); // TODO? let str = ' ' + FAILURE + (suite ? kleur.red(SUITE(` ${suite} `)) : '') + ' ' + QUOTE + kleur.red().bold(name) + QUOTE; str += '/n ' + err.message + (operator ? kleur.italic().dim(` (${operator})`) : '') + '/n'; if (details) str += GUTTER + details.split('/n').join(GUTTER); if (!!~idx) str += stack(err.stack, idx); return str + '/n'; } async function runner(ctx, name) { let { only, tests, before, after, bEach, aEach, state } = ctx; let hook, test, arr = only.length ? only : tests; let num=0, errors='', total=arr.length; try { if (name) write(SUITE(kleur.black(` ${name} `)) + ' '); for (hook of before) await hook(state); for (test of arr) { state.__test__ = test.name; try { for (hook of bEach) await hook(state); await test.handler(state); for (hook of aEach) await hook(state); write(PASS); num++; } catch (err) { for (hook of aEach) await hook(state); if (errors.length) errors += '/n'; errors += format(test.name, err, name); write(FAIL); } } } finally { state.__test__ = ''; for (hook of after) await hook(state); let msg = ` (${num} / ${total})/n`; let skipped = (only.length ? tests.length : 0) + ctx.skips; write(errors.length ? kleur.red(msg) : kleur.green(msg)); return [errors || true, num, skipped, total]; } } let timer; function defer() { clearTimeout(timer); timer = setTimeout(exec); } function setup(ctx, name = '') { ctx.state.__test__ = ''; ctx.state.__suite__ = name; const test = into(ctx, 'tests'); test.before = hook(ctx, 'before'); test.before.each = hook(ctx, 'bEach'); test.after = hook(ctx, 'after'); test.after.each = hook(ctx, 'aEach'); test.only = into(ctx, 'only'); test.skip = () => { ctx.skips++ }; test.run = () => { let copy = { ...ctx }; let run = runner.bind(0, copy, name); Object.assign(ctx, context(copy.state)); UVU_QUEUE[globalThis.UVU_INDEX || 0].push(run); isCLI || defer(); }; return test; } const suite = (name = '', state = {}) => setup(context(state), name); const test = suite(); async function exec(bail) { let timer = hrtime(); let done=0, total=0, skips=0, code=0; for (let group of UVU_QUEUE) { if (total) write('/n'); let name = group.shift(); if (name != null) write(FILE(name) + '/n'); for (let test of group) { let [errs, ran, skip, max] = await test(); total += max; done += ran; skips += skip; if (errs.length) { write('/n' + errs + '/n'); code=1; if (bail) return isNode && process.exit(1); } } } write('/n Total: ' + total); write((code ? kleur.red : kleur.green)('/n Passed: ' + done)); write('/n Skipped: ' + (skips ? kleur.yellow(skips) : skips)); write('/n Duration: ' + timer() + '/n/n'); if (isNode) process.exitCode = code; } exports.exec = exec; exports.suite = suite; exports.test = test;:150:42) at Object.exports.run (const { exec } = require('uvu'); exports.run = async function (suites, opts={}) { globalThis.UVU_DEFER = 1; suites.forEach((suite, idx) => { globalThis.UVU_INDEX = idx; require(suite.file); }); await exec(opts.bail); } :9:9) at C:/Users/gthet/Repositories/solid-primitives/packages/event-listener/node_modules/uvu/bin.js:28:30 ```
atk commented 2 years ago

Thanks for opening the issue. I'll have a closer look.

atk commented 2 years ago

Please try 0.1.5 now. Unfortunately, I cannot easily fix the wrong traces, but I can at least reduce them by not compiling '.js' by default, unless configured.