Code that throws a non-Error cannot be tested with hTest: the runner itself crashes, and the whole run goes down with it — not just the offending test.
Reproduction
package.json
t.js
export default { tests: [{ run: () => { throw "boom"; }, throws: true }] };
Expected: ✅ 1/1 PASS — throws: true says any throw satisfies the test.
Actual:
TypeError: Cannot use 'in' operator to search for 'actual' in boom
The process dies, so every other test file in the run is lost too.
Cause
in throws a TypeError when its right operand is not an object, so duck-typing the caught value crashes on any primitive.
Scope
Every primitive throw, with or without throws: true:
| Thrown value |
Result |
"boom" |
❌ Cannot use 'in' operator … in boom |
42 |
❌ Cannot use 'in' operator … in 42 |
null |
❌ Cannot use 'in' operator … in null |
undefined |
❌ Cannot use 'in' operator … in undefined |
new Error("boom") |
✅ works |
throws: true, throws: "boom" and a predicate are all unreachable — the crash happens before any of them is consulted.
Notes
Throwing a string is legal JS and shows up in real code (some libraries and older APIs reject with strings). Guarding the duck-type check would let those tests run and, more importantly, keep one bad test from taking down the run.
Code that throws a non-
Errorcannot be tested with hTest: the runner itself crashes, and the whole run goes down with it — not just the offending test.Reproduction
package.json{ "type": "module" }t.jsExpected:
✅ 1/1 PASS—throws: truesays any throw satisfies the test.Actual:
The process dies, so every other test file in the run is lost too.
Cause
htest/src/classes/TestResult.js
Line 119 in b6eb504
inthrows aTypeErrorwhen its right operand is not an object, so duck-typing the caught value crashes on any primitive.Scope
Every primitive throw, with or without
throws: true:"boom"Cannot use 'in' operator … in boom42Cannot use 'in' operator … in 42nullCannot use 'in' operator … in nullundefinedCannot use 'in' operator … in undefinednew Error("boom")throws: true,throws: "boom"and a predicate are all unreachable — the crash happens before any of them is consulted.Notes
Throwing a string is legal JS and shows up in real code (some libraries and older APIs reject with strings). Guarding the duck-type check would let those tests run and, more importantly, keep one bad test from taking down the run.