Skip to content

Commit

Permalink
refactor(lengthOf): favor it over length
Browse files Browse the repository at this point in the history
- The method part of the `length` assertion was slated for deprecation
  due to a compatibility issue in legacy environments. The decision to
  deprecate `length` was reversed per chaijs#684. This commit replaces the
  deprecation notice with a recommendation to favor `lengthOf` over
  `length` due to the compatibility issue.

- The `lengthOf` assertion wasn't a true alias of `length` because it
  was a method assertion instead of a chainable method assertion. This
  commit changes `lengthOf` into a chainable method assertion that's
  identical to `length`, and updates tests and docs accordingly.

- Updates docs to classify `length` as an alias of `lengthOf`.

- Updates docs of related assertions to use `lengthOf` instead of
  `length`.
  • Loading branch information
meeber committed Jan 2, 2017
1 parent 104a6b7 commit ae69f27
Show file tree
Hide file tree
Showing 5 changed files with 184 additions and 46 deletions.
82 changes: 42 additions & 40 deletions lib/chai/core/assertions.js
Original file line number Diff line number Diff line change
Expand Up @@ -674,14 +674,14 @@ module.exports = function (chai, _) {
*
* expect(10).to.be.above(5);
*
* Can also be used in conjunction with `length` to
* Can also be used in conjunction with `lengthOf` to
* assert a minimum length. The benefit being a
* more informative error message than if the length
* was supplied directly. In this case the target must
* have a length property.
*
* expect('foo').to.have.length.above(2);
* expect([ 1, 2, 3 ]).to.have.length.above(2);
* expect('foo').to.have.lengthOf.above(2);
* expect([ 1, 2, 3 ]).to.have.lengthOf.above(2);
*
* @name above
* @alias gt
Expand Down Expand Up @@ -736,14 +736,14 @@ module.exports = function (chai, _) {
*
* expect(10).to.be.at.least(10);
*
* Can also be used in conjunction with `length` to
* Can also be used in conjunction with `lengthOf` to
* assert a minimum length. The benefit being a
* more informative error message than if the length
* was supplied directly. In this case the target must
* have a length property.
*
* expect('foo').to.have.length.of.at.least(2);
* expect([ 1, 2, 3 ]).to.have.length.of.at.least(3);
* expect('foo').to.have.lengthOf.at.least(2);
* expect([ 1, 2, 3 ]).to.have.lengthOf.at.least(3);
*
* @name least
* @alias gte
Expand Down Expand Up @@ -796,14 +796,14 @@ module.exports = function (chai, _) {
*
* expect(5).to.be.below(10);
*
* Can also be used in conjunction with `length` to
* Can also be used in conjunction with `lengthOf` to
* assert a maximum length. The benefit being a
* more informative error message than if the length
* was supplied directly. In this case the target must
* have a length property.
*
* expect('foo').to.have.length.below(4);
* expect([ 1, 2, 3 ]).to.have.length.below(4);
* expect('foo').to.have.lengthOf.below(4);
* expect([ 1, 2, 3 ]).to.have.lengthOf.below(4);
*
* @name below
* @alias lt
Expand Down Expand Up @@ -858,14 +858,14 @@ module.exports = function (chai, _) {
*
* expect(5).to.be.at.most(5);
*
* Can also be used in conjunction with `length` to
* Can also be used in conjunction with `lengthOf` to
* assert a maximum length. The benefit being a
* more informative error message than if the length
* was supplied directly. In this case the target must
* have a length property.
*
* expect('foo').to.have.length.of.at.most(4);
* expect([ 1, 2, 3 ]).to.have.length.of.at.most(3);
* expect('foo').to.have.lengthOf.at.most(4);
* expect([ 1, 2, 3 ]).to.have.lengthOf.at.most(3);
*
* @name most
* @alias lte
Expand Down Expand Up @@ -918,14 +918,14 @@ module.exports = function (chai, _) {
*
* expect(7).to.be.within(5,10);
*
* Can also be used in conjunction with `length` to
* Can also be used in conjunction with `lengthOf` to
* assert a length range. The benefit being a
* more informative error message than if the length
* was supplied directly. In this case the target must
* have a length property.
*
* expect('foo').to.have.length.within(2,4);
* expect([ 1, 2, 3 ]).to.have.length.within(2,4);
* expect('foo').to.have.lengthOf.within(2,4);
* expect([ 1, 2, 3 ]).to.have.lengthOf.within(2,4);
*
* @name within
* @param {Number} start lowerbound inclusive
Expand Down Expand Up @@ -1212,39 +1212,41 @@ module.exports = function (chai, _) {
Assertion.addMethod('ownPropertyDescriptor', assertOwnPropertyDescriptor);
Assertion.addMethod('haveOwnPropertyDescriptor', assertOwnPropertyDescriptor);

/**
* ### .length
*
* Sets the `doLength` flag later used as a chain precursor to a value
* comparison for the `length` property.
*
* expect('foo').to.have.length.above(2);
* expect([ 1, 2, 3 ]).to.have.length.above(2);
* expect('foo').to.have.length.below(4);
* expect([ 1, 2, 3 ]).to.have.length.below(4);
* expect('foo').to.have.length.within(2,4);
* expect([ 1, 2, 3 ]).to.have.length.within(2,4);
*
* *Deprecation notice:* Using `length` as an assertion will be deprecated
* in version 2.4.0 and removed in 3.0.0. Code using the old style of
* asserting for `length` property value using `length(value)` should be
* switched to use `lengthOf(value)` instead.
*
* @name length
* @namespace BDD
* @api public
*/

/**
* ### .lengthOf(value[, message])
*
* Asserts that the target's `length` property has
* When invoked as a function, asserts that the target's `length` property has
* the expected value.
*
* expect([ 1, 2, 3]).to.have.lengthOf(3);
* expect('foobar').to.have.lengthOf(6);
*
* When used as a language chain, sets the `doLength` flag which is later used
* by the `above`, `below`, `least`, `most`, and `within` assertions for
* asserting that the target's `length` property falls within the expected
* range of values.
*
* expect('foo').to.have.lengthOf.above(2);
* expect([ 1, 2, 3 ]).to.have.lengthOf.above(2);
* expect('foo').to.have.lengthOf.below(4);
* expect([ 1, 2, 3 ]).to.have.lengthOf.below(4);
* expect('foo').to.have.lengthOf.at.least(3);
* expect([ 1, 2, 3 ]).to.have.lengthOf.at.least(3);
* expect('foo').to.have.lengthOf.at.most(3);
* expect([ 1, 2, 3 ]).to.have.lengthOf.at.most(3);
* expect('foo').to.have.lengthOf.within(2,4);
* expect([ 1, 2, 3 ]).to.have.lengthOf.within(2,4);
*
* Warning: It's recommended to use `lengthOf` instead of its alias `length`,
* even though `length` is shorter. This is due to a compatibility issue that
* prevents `length` (but not `lengthOf`) from being chained directly off of
* an uninvoked method such as `a`. For example:
*
* expect('foo').to.have.a.lengthOf(3); // passes as expected
* expect('foo').to.have.a.length(3); // throws error
*
* @name lengthOf
* @alias length
* @param {Number} length
* @param {String} message _optional_
* @namespace BDD
Expand All @@ -1271,7 +1273,7 @@ module.exports = function (chai, _) {
}

Assertion.addChainableMethod('length', assertLength, assertLengthChain);
Assertion.addMethod('lengthOf', assertLength);
Assertion.addChainableMethod('lengthOf', assertLength, assertLengthChain);

/**
* ### .match(regexp)
Expand Down
2 changes: 1 addition & 1 deletion lib/chai/interface/assert.js
Original file line number Diff line number Diff line change
Expand Up @@ -1456,7 +1456,7 @@ module.exports = function (chai, util) {
*/

assert.lengthOf = function (exp, len, msg) {
new Assertion(exp, msg).to.have.length(len);
new Assertion(exp, msg).to.have.lengthOf(len);
};

/**
Expand Down
6 changes: 3 additions & 3 deletions lib/chai/utils/overwriteChainableMethod.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ var transferFlags = require('./transferFlags');
* property. Must return functions to be used for
* name.
*
* utils.overwriteChainableMethod(chai.Assertion.prototype, 'length',
* utils.overwriteChainableMethod(chai.Assertion.prototype, 'lengthOf',
* function (_super) {
* }
* , function (_super) {
Expand All @@ -28,8 +28,8 @@ var transferFlags = require('./transferFlags');
*
* Then can be used as any other assertion.
*
* expect(myFoo).to.have.length(3);
* expect(myFoo).to.have.length.above(3);
* expect(myFoo).to.have.lengthOf(3);
* expect(myFoo).to.have.lengthOf.above(3);
*
* @param {Object} ctx object whose method / property is to be overwritten
* @param {String} name of method / property to overwrite
Expand Down

0 comments on commit ae69f27

Please sign in to comment.