From the documentation it doesn't seem like the following behaviour:
assert.notStrictEqual(3, '3', 'no coercion for strict equality');
is available for bdd style tests.
The only equality tests in the "expect" part of the library is this:
expect(3).to.equal('3');
but that will fail because it uses === for the comparison.
Is there any way to get the same behaviour as notStrictEqual for expect?
Looking at the code notStrictEqual is merely to.not.equal
/**
* ### .notStrictEqual(actual, expected, [message])
*
* Asserts strict inequality (`!==`) of `actual` and `expected`.
*
* assert.notStrictEqual(3, '3', 'no coercion for strict equality');
*
* @name notStrictEqual
* @param {Mixed} actual
* @param {Mixed} expected
* @param {String} message
* @api public
*/
assert.notStrictEqual = function (act, exp, msg) {
new Assertion(act, msg).to.not.equal(exp);
};
Sounds more like you want the equivalent of the following on the expect side.
At the moment there does not appear to be a non-strict equality check there.
/**
* ### .equal(actual, expected, [message])
*
* Asserts non-strict equality (`==`) of `actual` and `expected`.
*
* assert.equal(3, '3', '== coerces values to strings');
*
* @name equal
* @param {Mixed} actual
* @param {Mixed} expected
* @param {String} message
* @api public
*/
assert.equal = function (act, exp, msg) {
var test = new Assertion(act, msg, assert.equal);
test.assert(
exp == flag(test, 'object')
, 'expected #{this} to equal #{exp}'
, 'expected #{this} to not equal #{act}'
, exp
, act
);
};
Looking at this a bit further it appears non strict equality checking is one of the very few things not pulled over. I'm unsure why its even left in this all together. Personally I don't believe it should be. To me loose equality checking is bad practice.
I understand that loose equality checking is bad practice in general but I would like to make a case for it in a testing environment.
We are currently using mockgoose (a mongoose wrapper) which allows us to quickly mock out all DB functions to an in memory store. Because It's based in mongodb we have the strangeness of needing to use MongoID objects whenever we would like to specify the ID of an object.
our use case is this expect(results[0].user.userId).to.equal(session.userId); where userId is a MongoID object. With the above we get the following error:
AssertionError: expected '53ce1023a430bc2a15fdd060' to equal 53ce1023a430bc2a15fdd060
so in all cases where we are trying to compare IDs we would need to change it to:
expect(results[0].user.userId).to.equal(session.userId.toString());
I know I'm falling into the realm of first-world-problems here but having some sort of option to allow chai to coerce a MongoID into a string would make this cleaner in a lot of cases for us.
The absence of this API also prevents comparing strings created using the new operator:
expect('hi').to.equal(new String('hi')) // will fail
Our use case for using the new operator with Strings is that we're actually comparing instances of a string subclass.
If Chai wants to claim that loose equality checking is bad practice, that makes sense to me鈥攖hough I would find it disappointing, as Chai is very flexible in most other respects鈥攂ut it doesn't make sense to me that it's exposed by one of Chai's APIs and not another.
Hey @wearhere.
If you want to avoid casting string subclass to primitive on every assertion, I believe may want to write a plugin that adds a getter like .loose that sets a flag on an assertion, and overwrite equal method to respect that flag. Something like:
expect('hi').to.loose.equal(new String('hi'))
@shvaikalesh I particularly like that idea of adding a .loose differentiator API 馃憤 that would be exactly what would have solved my problem.
@shvaikalesh I like that idea, though as far as it becoming a plugin I'll say that it not being built into core is a hindrance coming from Jasmine, which offers expect鈥oBe (strict) vs. expect鈥oEqual (loose) out of the box.
I made my own plugin that supports loose equality for my use cases. At the moment it always deeply compares the inputs, and it only supports arrays and other non-object primitives. I can make it more robust and put it on NPM if anyone feels it would be useful to them
@nadrane why not contribute it as a PR to chai?
Most helpful comment
Hey @wearhere.
If you want to avoid casting string subclass to primitive on every assertion, I believe may want to write a plugin that adds a getter like
.loosethat sets a flag on an assertion, and overwriteequalmethod to respect that flag. Something like: