chai icon indicating copy to clipboard operation
chai copied to clipboard

assert.throws does not perform equality check against Error message

Open Caligatio opened this issue 4 years ago • 4 comments

It appears that assert.throws does some sort of .endsWith comparison instead of an equality check if provided 2 arguments and the second argument is a string. From the docs:

assert.throws(fn, 'Error thrown must have this msg');

This definitely makes me believe that the string provided should match the Error message. However, I discovered the following:

import { describe, it } from "mocha";
import { assert } from "chai";

describe("Test throws", () => {
  const errMsg = "ABCD is a bad value";

  // Passes as expected
  it("Full Comparison", () => {
    assert.throws(() => {
      throw new Error(errMsg);
    }, errMsg);
  });

  // ERROR: this unexpectedly passes
  it("endsWith Comparison", () => {
    assert.throws(() => {
      throw new Error(errMsg);
    }, "bad value");
  });

  // Fails as expected
  it("Bad Comparison", () => {
    assert.throws(() => {
      throw new Error(errMsg);
    }, "good value");
  });
});

Caligatio avatar Apr 15 '20 05:04 Caligatio

Digging through the code, I found the offending line (https://github.com/chaijs/chai/blob/master/chai.js#L9576) which uses an indexOf rather than equality.

function compatibleMessage(thrown, errMatcher) {
  var comparisonString = typeof thrown === 'string' ? thrown : thrown.message;
  if (errMatcher instanceof RegExp) {
    return errMatcher.test(comparisonString);
  } else if (typeof errMatcher === 'string') {
    return comparisonString.indexOf(errMatcher) !== -1; // eslint-disable-line no-magic-numbers
  }

  return false;
}

The naming of the function makes me think not using equality was deliberate but this is incorrect behavior,

Caligatio avatar Apr 16 '20 19:04 Caligatio

The same

GABAnich avatar Feb 19 '21 19:02 GABAnich

I'm also faced this issue. And it is a bug, because partial match can be performed with RegExp, so case with string should check exact match.

1aerostorm avatar May 08 '21 18:05 1aerostorm

I also came across this issue along with the same strange compatibleMessage behavior. This behavior is documented in the code and in the .throw() documentation here, so I guess it's not really a bug, but it does seem counter-intuitive (and risky).

iancamp avatar May 04 '22 17:05 iancamp