chai doesn't catch an error has thrown
this is my test
which fails with the message:
1) Test suite for quickSort function
#16. The comparer function is not specified in attributes. In this case,
an array of objects can't be sorted because compare function doesn't know
how so quickSort() throws TypeError:
TypeError: Default compare function for arrays of objects is not supported
at quickSort ...
at Context.<anonymous> ...
at processImmediate ...
but other similar test passed:
I couldn't find any explanations / solutions / workarounds for this, so I think it's a bug with the expect(x).to.throw assertion.
@MakariukVl Can you provide a minimum viable code that reproduces the issue?
Yes of course @koddsson, I will attach the code. The quickSort function should cause an error in line 24 if the input array is an object array. The error itself is called, test No16 (line 209) must verify this, but chai doesn't catch this error. Another similar test No15 passed.
quicksort.js
function quickSort(array, compare) {
const INPUT_TYPE = Object.prototype.toString.call(array);
const ARRAY_TYPE = "[object Array]";
const OBJECT_TYPE = "[object Object]";
const STRING_TYPE = "[object String]";
if (!(INPUT_TYPE === ARRAY_TYPE) && !(INPUT_TYPE === STRING_TYPE))
throw new TypeError("The 'array' property must be an Array or String");
if (array.length < 2) return array;
compare = compare || null;
if (INPUT_TYPE === ARRAY_TYPE) {
if (array.filter(Array.isArray).length >= 1 && compare == null) {
throw new TypeError(
"Default compare function for multidimensional arrays is not supported"
);
}
if (
array.filter((v) => Object.prototype.toString.call(v) === OBJECT_TYPE)
.length >= 1 &&
compare == null
) {
throw new TypeError(
"Default compare function for arrays of objects is not supported"
);
}
}
let result, cmp;
if (INPUT_TYPE === STRING_TYPE) {
cmp = (a, b) => a.localeCompare(b);
let str = array.split("");
result = sort(str, cmp).join("");
} else {
// INPUT_TYPE === ARRAY_TYPE
cmp =
compare ||
function (a, b) {
return a - b;
};
result = sort(array, cmp);
}
return result;
function sort(arr, cmp) {
var left = [];
var right = [];
var indexMid = Math.floor(arr.length / 2);
var mid = arr[indexMid];
for (let i = 0; i < arr.length; i++) {
if (i === indexMid) continue;
if (cmp(mid, arr[i]) > 0) left.push(arr[i]);
else right.push(arr[i]);
}
let result = [];
result.push(...quickSort(left, cmp));
result.push(mid);
result.push(...quickSort(right, cmp));
return result;
}
}
export { quickSort };
quicksort.test.js
// chai: https://github.com/chaijs/chai
import chai from "chai";
// chaiArrays: https://github.com/GaneshSPatil/chai-arrays
import chaiArrays from "chai-arrays";
import { quickSort } from "../src/quickSort.js";
const expect = chai.expect;
chai.use(chaiArrays);
describe("Test suite for quickSort function", function () {
....
it("#15. The comparer function is not specified in attributes. In this case,\n\t2d array can't be sorted because compare function doesn't know how so \n\tquickSort() throws TypeError", function () {
const arr = [
[50, 86],
[77, 2],
[90, 8],
[7, 8],
[1, 2],
[13, 8],
[2, 10],
[33, 24],
];
expect(quickSort.bind(null, arr)).to.throw(TypeError);
});
it("#16. The comparer function is not specified in attributes. In this case,\n\tarray of objects can't be sorted because compare function doesn't know\n\thow so quickSort() throws TypeError", function () {
const arr = quickSort([
{ Name: "Bob", Age: 17 },
{ Name: "Daniel", Age: 33 },
{ Name: "Clara", Age: 41 },
{ Name: "Ann", Age: 15 },
{ Name: "John", Age: 36 },
{ Name: "Jane", Age: 31 },
{ Name: "Jack", Age: 70 },
{ Name: "Sara", Age: 7 },
]);
// Bug - chai doesn't catch an error has thrown: https://github.com/chaijs/chai/issues/1414
expect(quickSort.bind(null, arr)).to.throw(TypeError);
});
....
});
Hey there,
I was experiencing a similar situation.
This basic example should run the tests as expected without exiting.
// someFunction.js
export default function someFunction(arg) {
if (!arg) {
throw new Error("Oops")
}
}
and testfile:
import "chai/register-should.js"
import someFunction from "./someFunction.js"
describe("someFunction()", function functionName() {
it("should throw without arguments", function () {
someFunction.should.throw()
})
it("should not throw with an argument", function () {
(()=> someFunction("argument")).should.not.throw()
})
})
You should pay attention to catching errors in your other tests and code usage where you use / instanciate a function that throws errors on wrong usage. If you don't, testing will exit with the actual error thrown.
In my situation I was instanciating someFunction without arguments in another describe block, like:
// describe block
const value = someFunction()
which caused my tests to stop running due to thrown error.
In your case the code exits because somewhere you throw an error when an array with objects is passed:
throw new TypeError("Default compare function for arrays of objects is not supported");
Due to quickSort being a kind of recursive function calling quickSort again with different arguments might cause your tests to exit. It did not throw the error with first call, but quickSort got called again internally which threw the error that did not get caught. So your test did not pass or fail.
Should chai.should.throw also catch errors that occur in this situation as well? Whilst running the initial called tested function?