Giter VIP home page Giter VIP logo

should.js's Introduction

should.js

Join the chat at https://gitter.im/shouldjs/should.js

Build Status

Selenium Test Status

should is an expressive, readable, framework-agnostic assertion library. The main goals of this library are to be expressive and to be helpful. It keeps your test code clean, and your error messages helpful.

By default (when you require('should')) should extends the Object.prototype with a single non-enumerable getter that allows you to express how that object should behave. It also returns itself when required with require.

It is also possible to use should.js without getter (it will not even try to extend Object.prototype), just require('should/as-function'). Or if you already use version that auto add getter, you can call .noConflict function.

Results of (something).should getter and should(something) in most situations are the same

Upgrading instructions

Please check wiki page for upgrading instructions.

FAQ

You can take look in FAQ.

Example

var should = require('should');

var user = {
    name: 'tj'
  , pets: ['tobi', 'loki', 'jane', 'bandit']
};

user.should.have.property('name', 'tj');
user.should.have.property('pets').with.lengthOf(4);

// If the object was created with Object.create(null)
// then it doesn't inherit `Object.prototype`, so it will not have `.should` getter
// so you can do:
should(user).have.property('name', 'tj');

// also you can test in that way for null's
should(null).not.be.ok();

someAsyncTask(foo, function(err, result){
  should.not.exist(err);
  should.exist(result);
  result.bar.should.equal(foo);
});

To begin

  1. Install it:

    $ npm install should --save-dev
  2. Require it and use:

    var should = require('should');
    
    (5).should.be.exactly(5).and.be.a.Number();
    var should = require('should/as-function');
    
    should(10).be.exactly(5).and.be.a.Number();
  3. For TypeScript users:

    import * as should from 'should';
    
    (0).should.be.Number();

In browser

Well, even when browsers by complaints of authors have 100% es5 support, it does not mean it has no bugs. Please see wiki for known bugs.

If you want to use should in browser, use the should.js file in the root of this repository, or build it yourself. To build a fresh version:

$ npm install
$ npm run browser

The script is exported to window.should:

should(10).be.exactly(10)

You can easy install it with npm or bower:

npm install should -D
# or
bower install shouldjs/should.js

API docs

Actual api docs generated by jsdoc comments and available at http://shouldjs.github.io.

Usage examples

Please look on usage in examples

.not

.not negates the current assertion.

.any

.any allow for assertions with multiple parameters to assert any of the parameters (but not all). This is similar to the native JavaScript array.some.

Assertions

chaining assertions

Every assertion will return a should.js-wrapped Object, so assertions can be chained. To help chained assertions read more clearly, you can use the following helpers anywhere in your chain: .an, .of, .a, .and, .be, .have, .with, .is, .which. Use them for better readability; they do nothing at all. For example:

user.should.be.an.instanceOf(Object).and.have.property('name', 'tj');
user.pets.should.be.instanceof(Array).and.have.lengthOf(4);

Almost all assertions return the same object - so you can easy chain them. But some (eg: .length and .property) move the assertion object to a property value, so be careful.

Adding own assertions

Adding own assertion is pretty easy. You need to call should.Assertion.add function. It accept 2 arguments:

  1. name of assertion method (string)
  2. assertion function (function)

What assertion function should do. It should check only positive case. should will handle .not itself. this in assertion function will be instance of should.Assertion and you must define in any way this.params object in your assertion function call before assertion check happen.

params object can contain several fields:

  • operator - it is string which describe your assertion
  • actual it is actual value, you can assume it is your own this.obj if you need to define you own
  • expected it is any value that expected to be matched this.obj

You can assume its usage in generating AssertionError message like: expected obj? || this.obj not? operator expected?

In should sources appeared 2 kinds of usage of this method.

First not preferred and used only for shortcuts to other assertions, e.g how .should.be.true() defined:

Assertion.add('true', function() {
    this.is.exactly(true);
});

There you can see that assertion function do not define own this.params and instead call within the same assertion .exactly that will fill this.params. You should use this way very carefully, but you can use it.

Second way preferred and i assume you will use it instead of first.

Assertion.add('true', function() {
    this.params = { operator: 'to be true', expected: true };

    should(this.obj).be.exactly(true);
});

in this case this.params defined and then used new assertion context (because called .should). Internally this way does not create any edge cases as first.

Assertion.add('asset', function() {
    this.params = { operator: 'to be asset' };

    this.obj.should.have.property('id').which.is.a.Number();
    this.obj.should.have.property('path');
})

//then
> ({ id: '10' }).should.be.an.asset();
AssertionError: expected { id: '10' } to be asset
    expected '10' to be a number

> ({ id: 10 }).should.be.an.asset();
AssertionError: expected { id: 10 } to be asset
    expected { id: 10 } to have property path

Additional projects

  • should-sinon - adds additional assertions for sinon.js
  • should-immutable - extends different parts of should.js to make immutable.js first-class citizen in should.js
  • should-http - adds small assertions for assertion on http responses for node only
  • should-jq - assertions for jq (need maintainer)
  • karma-should - make more or less easy to work karma with should.js
  • should-spies - small and dirty simple zero dependencies spies

Contributions

Actual list of contributors if you want to show it your friends.

To run the tests for should simply run:

$ npm test

See also CONTRIBUTING.

OMG IT EXTENDS OBJECT???!?!@

Yes, yes it does, with a single getter should, and no it won't break your code, because it does this properly with a non-enumerable property.

Also it is possible use it without extension. Just use require('should/as-function') everywhere.

License

MIT. See LICENSE for details.

should.js's People

Contributors

alfred-nsh avatar alsotang avatar aseemk avatar awk34 avatar btd avatar citizensas avatar fediev avatar fredr avatar gabrielfalcao avatar nbrownus avatar nickdaugherty avatar prayagverma avatar qix- avatar rafmagana avatar raynos avatar rixth avatar rubenverborgh avatar rudolf avatar sergiitk avatar shubhodeep9 avatar skovalyov avatar spencesellers avatar theycallmeswift avatar tj avatar tonylukasavage avatar tootallnate avatar travisjeffery avatar tricknotes avatar vlad-shatskyi avatar vp2177 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

should.js's Issues

`should.not.equal(complexObject)` is not optimal

Assuming we have two complex objects, such as registry1 and registry2, the following assertion becomes very expensive:

registry1.should.not.equal(registry2)

should at the moment always asserts the equal first, creates an AssertionError, and then tests the not condition by catching the error. See https://github.com/shouldjs/should.js/blob/master/lib/assertion.js#L47-L68. For complex objects, the getMessage is very expensive (in our case, more than 4 seconds).

The work around is to provide a custom message for the assertion. I wonder if the assert could check the negate flag and only construct a dummy AssertionError if negate is true?

See loopbackio/loopback-datasource-juggler#431

.include deprecated...why? Where is the discussion about this?

I'm trying to figure out what was changed and why, in the changes file it only says include and includeEql were deprecated but no guidance and no explanation and from what I can find no issues or discussion about it.

Where was the conversation? If there was none can someone explain why it was removed?

instanceOf(Error) should.not.be.ok

This is just a suggestion.

If a developer returns an Error object the intent of the return is likely to indicate whatever was happening is not.ok, therefor I think it would be nice if is.ok would fail and not.ok succeed.

Current:

return false;             // not ok
return Error('not ok');   // ok

Suggested:

return false;             // not ok
return Error('not ok');   // not ok

Right now they will just pass, because Error is not falsey.

I think the worst that can happen by applying this change is test failing with uncought return errors.

Performance wise it might cost a millisecond. (which could be tested on a larger test suite)

But I think it would be rather useful compared to val.should.be.instanceOf(Error), which will require you to rewrite tests if you decide to return error objects instead of just false.

Also test writers could falsely assume the code is doing what is expected, because things seem to be ok.

Should "eql" comparing prototypes?

Version 4.4 is breaking compatibility with 4.3, because module should-equal is comparing not only paths but also prototypes.

{
  result: false,
  path: [],
  reason: 'A and B have different prototypes',
  a: { a: 2 },
  b: { a: 2 } 
}

Previously objects a and b was asserted as equal - now, they are different.

Is this change intended? If so:

  • this should be mentioned somewhere
  • what should I use for old behavior?

Nested empty objects are compared as equal by .containDeep

Example:

require('should');

var obj = {
  prop: {
    nestedProp1: [],
    nestedProp2: 123
  }
}

obj.should.containDeep({ prop: { nestedProp1: [], nestedProp2: 123 } });
obj.should.containDeep({ prop: { nestedProp1: [] } });
obj.should.containDeep({ prop: { nestedProp2: 123 } });
obj.should.containDeep({ prop: {} }); // Throws an error

Prior to version v4.6.4 this would not have thrown an Error and is the behaviour I would expect from .containEql.

I notice that commit 1e49897 changes this behaviour but I didn't have time to work out if this was the intended change in functionality.

Add something equivalent to chai expect .members

Say I have an array and I need to compare it to another array:

expected = [1,2,3];
actual = [1,2,3];
expected.should.eql(actual);

This works fine. However, if the order is different, it fails:

expected = [1,2,3];
actual = [1,3,2];
expected.should.eql(actual);

I could use should.containDeep, which will pass, but it will also allow something like this to pass:

expected = [1,2,3];
actual = [3,3,3];
expected.should.containDeep(actual);

The best solution I can find currently is to sort the two arrays and then use should.eql:

expected = [1,2,3];
actual = [1,3,2];

// sort both arrays in place to ensure same ordering
expected.sort()
actual.sort()

expected.should.eql(actual);

This works, but it would be great if the same idea was built in more naturally. The Chai expect library has a .members function which would be a good model:

expected = [1,2,3];
actual = [1,3,2];
expect(expected).to.have.members(actual);

Rather than having the notion of ordering involved, this simply ensures expected has exactly the same members as actual. It goes beyond containment, ensuring all members have a matching member in the other array. So for instance, it will fail if actual = [1,3].

Confusing positives for is.a.<anything>

I've noticed non-existing matchers will not throw an error.

var n = 1;

n.is.a.Number;   // true
n.is.a.number;   // true
n.is.a.anything;  // true
n.is.a.string;      // true
n.is.a.function;  // true

n.is.a.String; // false
n.is.a.Function; // false

It can be quite confusing when things seem to match, but in reality they are false.

Is this intended behavior or an artifact?

ES6 generator throw assert

The function for the .should.throw() assertion doesn't allow for generator functions to be used.

(function * () {
  yield throwsError();
}).should.throw();

Instead we have to use the iterator on the generator throwing an error like so:

(function () {
  var f = throwsError();
  f.next();
}).should.throw();

It would be useful if it could work, like we do for the normal use of the assertion.

(function () {
  throw new Error();
}).should.throw();

Is it possible to add support for more expressive eql reporting?

Look at the following:

var a = {a:1,b:2,c:3,d:4,e:5,f:6,g:7,h:8,i:9,j:10},
b = {a:1,b:2,c:3,d:4,e:5,f:6,g:7,h:7,i:9,j:10};

a.should.eql(b);

a and b both have 10 properties. Only one is off. eql() does a good job comparing them, but the report will look something like:

AssertionError: expected {a:1,b:2,c:3,d:4,e:5,f:6,g:7,h:8,i:9,j:10} to equal {a:1,b:2,c:3,d:4,e:5,f:6,g:7,h:7,i:9,j:10}

That requires digging through each property to find which one doesn't match, or if one has an extra property, or the other. Imagine if this was an array of 50 items, or an object with 100 properties.

eql() already does this work and knows exactly why the 2 don't match. Is it possible to make it so that the error message can tell us exactly which prop exists on a and not b, which on b and not a, and which on both but doesn't match?

I would probably do it as eqlDetail() or something weird like that, or perhaps an option to eql() as a.should.eql(b,true) so as not to break backwards compatibility.

Thoughts?

4.2.0 + mocha + underscore = slow ?

I tried to recreate the problem I am having in a simple example but was unable. I think that I need to perform the should operation that is, seemingly, operating slow on the my codes object and not just a json output of it.

The below operation seems to be taking an extremely long time. Longer than 2 seconds on a =~ 20 item list.

items.should.have.property('length').and.be.greaterThan(0);

The same operation works fine on 4.1.0.

I know this isn't much information but maybe it will trigger some thought about what has changed with respect to the functionality mentioned between 4.1.0 and 4.2.0.

Let me know if you need more information and I'll try to "export" the object into a small/reproducible chunk.

IE 9

Is support going to come back for ie9?

undocumented breaking changes between 3.3.2 and 4.0.0

The whole file libs/ext/http.js got removed so this code fails in 4.0.0
see: 3.3.2...4.0.0

response.should.have.header('set-cookie')
Object #<Assertion> has no method 'header'

for completeness sake this deletion should be added to the wiki: https://github.com/shouldjs/should.js/wiki/Breaking-changes-4.x
by the changes' author himself

what is the equivalent of the header function in 4.0.0?

maybe:

response.headers.should.have.property 'Set-Cookie'

Chai-like "expect" API

I am pondering the idea of moving from "chai" to "should.js", mostly because "should.js" has more assertions and supports to.be.true() function calls.

However, I really dislike actual.should... syntax, as it reports ugly failure messages when actual happens to be null or undefined.

Would you accept a pull request adding a new API "expect"?

var should = require('should');
var expect = should.expect;
expect(actual).to.equal(10); 
// initialise Assertion instance with obj=10 and call the "equal" checker

How to use propertyByPath with a value?

For example, there is a object:

var o = {
   a : {
     b: 1
   }
};

And I want to know whether o.a.b === 1
My code is like below, but it seems not work:confused::

o.should.have.propertyByPath('a', 'b', 1);

.should.match always matches for Error objects

When using .should.match on Error objects, the assertion always passes, even if it should fail. For example, if you create an Error:

err = new Error("This is not the error I want");

When matching against a RegExp manually, you get the expected results:

/This is the error I want/.test(err);
// Returns false, as expected

However, when using .should.match, the assertion will pass anyway:

err.should.match(/This is the error I want/);
// Does not throw an AssertionError

Feature Request: Occurrences

I often find myself needing to count the number of times a string exists in another string. Right now I'm using the great occurrences function:

var str = "Wikitext '''bold''' is three single quotes";
occurences(str, "'''").should.eql(2);

I imagine the same kind of test could be applied to arrays whereby it counts the number of times a thing exists in the given array.

(Or, if this already exists, I guess document it?)

should.Assertion undefined

should.Assertion.add('jqPromise', function () {
  this.params = { operator: 'to be jQuery Deferred / Promise' };

  this.then.should.be.type('function');
  $.Deferred().then.toString().should.equal(this.then.toString());
}, true);

Uncaught TypeError: Cannot read property 'add' of undefined

Basically, I have no should.Assertion 😞

I'm loading it in the browser like so. What am I doing wrong?

<script src="node_modules/should/should.js"></script>

fails in browserify

Error: Parsing file /Users/contra/Projects/famous/famous-react/node_modules/should/lib/should.js: Line 167: Unexpected token {
    at Deps.parseDeps (/Users/contra/Projects/famous/famous-react/node_modules/mochify/node_modules/browserify/node_modules/module-deps/index.js:360:28)
    at fromSource (/Users/contra/Projects/famous/famous-react/node_modules/mochify/node_modules/browserify/node_modules/module-deps/index.js:303:48)
    at /Users/contra/Projects/famous/famous-react/node_modules/mochify/node_modules/browserify/node_modules/module-deps/index.js:298:17
    at ConcatStream.<anonymous> (/Users/contra/Projects/famous/famous-react/node_modules/mochify/node_modules/browserify/node_modules/concat-stream/index.js:32:43)
    at ConcatStream.emit (events.js:117:20)
    at finishMaybe (/Users/contra/Projects/famous/famous-react/node_modules/mochify/node_modules/browserify/node_modules/concat-stream/node_modules/readable-stream/lib/_stream_writable.js:460:14)
    at endWritable (/Users/contra/Projects/famous/famous-react/node_modules/mochify/node_modules/browserify/node_modules/concat-stream/node_modules/readable-stream/lib/_stream_writable.js:469:3)
    at ConcatStream.Writable.end (/Users/contra/Projects/famous/famous-react/node_modules/mochify/node_modules/browserify/node_modules/concat-stream/node_modules/readable-stream/lib/_stream_writable.js:436:5)
    at DuplexWrapper.onend (/Users/contra/Projects/famous/famous-react/node_modules/mochify/node_modules/browserify/node_modules/duplexer2/node_modules/readable-stream/lib/_stream_readable.js:537:10)
    at DuplexWrapper.g (events.js:180:16)

Looks like it is dying here https://github.com/shouldjs/should.js/blob/master/lib/should.js#L165-L168

This is an issue with their parser since this is valid JS, just opening this here for reference if anyone else hits this

should.js crashing Chrome

/* global describe, it */

'use strict';

describe('Crashing chrome :/', function () {
  var promise;

  it('should create promise', function () {
    var defer = $.Deferred();

    setTimeout(function () {
      defer.resolve({ foo: 'bar' });
    }, 10);

    return (promise = defer.promise());
  });

  it('should have foo', function () {
    promise = promise.then(function (data) {
      data.should.have.property('foo');

      return data;
    });
    return promise;
  });

  it('shouldnt crash!!', function () {
    promise = promise.then(function (data) {
      data.html = $('<div />');
      return data;
    });

    return promise.then(function (data) {
      ({}).should.not.have.property('bla'); // This line does not crash it
//      data.should.have.property('foo'); // This line does
    });
  });
});

For some reason, adding a jQuery object to data and then running should on data causes CPU usage to increase to 100% forever and the test to hang.

This only happens in Chrome (38.0.2125.104), so I suspect it's a bug in Chrome. Do you know a workaround / fix?

Add matchAny assertion

For checking if one or more of an object's values or array elements match a given value/regexp/function.

Similar to matchEach, but passes if one or more values pass.

Breaking changes!?

Ok, clearly since half my tests are now broken I'd really be interested in finding more out about these breaking changes briefly mentioned but apparently utterly undocumented in the "wiki" for it.

Can anyone tell me where the discussion in advance was about them so I can understand them further and understand what I need to be looking at in future to avoid just getting slammed by this out of the blue like I did after updating yesterday?

And can someone update the wiki with links to and explanations of the breaking changes and the tools required to fix them?

Error: Failed to read the 'responseXML' property from 'XMLHttpRequest'

data.should.have.property('container');

Causes the following error to be thrown:

Error: Failed to read the 'responseXML' property from 'XMLHttpRequest': The value is only accessible if the object's 'responseType' is '' or 'document' (was 'arraybuffer').
    at Error (native)
    at Function.getOwnPropertyDescriptor (native)
    at formatProperty (http://localhost:3000/node_modules/should/should.js:1519:17)
    at http://localhost:3000/node_modules/should/should.js:1432:14
    at Array.map (native)
    at formatValue (http://localhost:3000/node_modules/should/should.js:1431:19)
    at formatProperty (http://localhost:3000/node_modules/should/should.js:1537:15)
    at http://localhost:3000/node_modules/should/should.js:1432:14
    at Array.map (native)
    at formatValue (http://localhost:3000/node_modules/should/should.js:1431:19)

I don't see how it's related, but it goes when I comment it out.

There is no AJAX anywhere in my code or my tests.

Strict equality check for arrays

The following assertion fails:

[1, 2, 3].should.equal([1, 2, 3]); // fails

I know that I can use .eql, but that causes loose comparison to be used on the array items too:

[1, 2, 3].should.eql([1, 2, 3]); // passes
[1, 2, 3].should.eql(['1', '2', '3']); // this also passes

Suggested enhancement: a new assertion that strictly compares values unless they are an Array/Object.

weird behavior when should set global

Should can't be used when set global in node, example:

describe("test suite", function() {

    it("this works", function() {

        var should = require("should");

        should(null).eql(null);

    });

    it("why does this throw an error?", function() {

        global.should = require("should");

        should(null).eql(null);

    });

});

the trhown error is: "TypeError: Property 'should' of object # is not a function"

Unexpected behavior when evaluating similar strings with .containDeep()

Replication steps

// fails
['code-for-days', 'code'].should.containDeep(['code', 'code-for-days'])

// passes
['code-for-days', 'code-fast'].should.containDeep(['code-fast', 'code-for-days'])

// also passes (ordered)
['code', 'code-for-days'].should.containDeep(['code', 'code-for-days'])

Incorrect assertion is made when similar strings are tested using this method.

It appears to me that .containDeep() is traversing strings as arrays (e.g. 'foo'[0] === 'f') and asserting as if these are nested arrays.

Creating assertion function from should

Can I get assertion function from should?

What I want to achieve:

var assertion = should.have.property('contents', 'data');
assertion({contents: 'nodata'}); // bam! exception

May be there are ready solution for this?

Strange behavior with equal

If I use

body.should.be.equal({response: 'ok'});

to test if a response returns the right content, the test fails because it says the result is not identical, but they are. Here is the error:

AssertionError: expected { response: 'ok' } to be { response: 'ok' }

And here the expected

{
  "response": "ok"
}

and the given return value

{
  "response": "ok"
}

Which are obviously the same.

chain's object not being set to value of property when calling .property()

According to the doc for .property():

.property changes the chain's object to the given property's value, so be careful when chaining after .property!

I want to check that my object k has a property foo and that k.foo is equal to 'chicken'. I expect the following to accomplish that:

var k = {
    'foo': 'chicken'
}

k.should.have.property('foo')
    .and.should.equal('chicken')

but instead, it looks like the chain's object is not being set to the value of k.foo, but rather, a different object. I get the following error:

AssertionError: expected { obj: 'chicken',
 params: { operator: 'to have property foo' },
 negate: false } to be 'chicken'

Am I missing something?

Thanks for the help.

should throw on not-a-function

> "hi".should.throw()
{ obj: 'hi',
  params: { operator: 'to throw exception (got [TypeError: string is not a function])' },
  negate: false }

> (1).should.throw()
{ obj: 1,
  params: { operator: 'to throw exception (got [TypeError: number is not a function])' },
  negate: false }

Shouldn't it be checked that obj is actually a function? This leads to bugs due to improper API use.

should.exist is undefined in chrome

I have tried including both the minified and non-minified versions of should.js from the master repo.
When I call:

should.exist(true)

I get this error back:

TypeError: undefined is not a function

What I found really strange, is that if I put a breakpoint right before should.exist is assigned, and then step over it, should.exist is still undefined!

//BREAKPOINT HERE

should.exist = should.exists = function (obj, msg) {
    if (null == obj) {
        throw new AssertionError({
            message: msg || ('expected ' + i(obj) + ' to exist'), stackStartFunction: should.exist
        });
    }
};

//should.exist and should.exists are both still undefined here

My chrome version is 36.0.1985.125 m.

I have also tried this in Firefox v30 with the same results.

timeout error when integrate with promise

Hi:
I have encounter a little problem when use shouldjs with Promise:

var should = require('should');

describe('promise assert', function () {
    it('normal assert', function (done) {
        var first = Promise.resolve('A');
        first.then(function(value) {
            value.should.equal('A');
            done();
        })
    });

    it('timeout assert', function (done) {
        var first = Promise.resolve('A');
        first.then(function(value) {
            value.should.equal('AB');
            done();
        })
    });
});

qq20141130-1

the first test-case passed, while the second test-case encounter timeout error, not fail assert. I still can't find reason out.

proper management

To keep things consistent, wouldn't it be better to move should as a project, rather than fork it? The guys over at jshttp / pillarjs have also moved ownership rather than forked the project. Imo that would add more consistency and prevent confusion for new users (e.g. opening issues on the wrong project, etc.)

containDeep doesn't compare Dates inside of objects correctly

I'm using node v0.10.36 with the latest version of should (v4.6.2) and am seeing the opposite result as I'd expect from containDeep when comparing Dates inside of objects.

Example:

var firstDec = [{date: (new Date('2014-12-01 00:00:00'))}];
var secondDec = [{date: (new Date('2014-12-02 00:00:00'))}];
firstDec.should.not.containDeep(secondDec); // Throws an AssertionError
firstDec.should.containDeep(secondDec); // No AssertionError

Output:

AssertionError: expected [
  { date: Monday, December 01, 2014 00:00:00.000 GMT-0000 }
] not to contain [
  { date: Tuesday, December 02, 2014 00:00:00.000 GMT-0000 }
]

Behaviour change without major version bump.

It seems the behaviour of eql has changed but without bumping the major version. All of my project use should.js with ^4.0.4 (for example) in the package.json. I've done a fresh npm install in one of my projects and it errored where it didn't before.

This change seems to have occurred in v4.3.0.

I have a repo here that reproduces the issue.

My main issue is that this is a behaviour change which will be pulled in for any projects that use the ^ in the package.json.

vagrant@devenv:~/test-should-versions$ mocha


  should 4.0.4
    ✓ should pass 

  should 4.1.0
WARN Strict version of eql return different result for this comparison
WARN it means that e.g { a: 10 } is equal to { a: "10" }, make sure it is expected
WARN To disable any warnings add should.warn = false
WARN If you think that is not right, raise issue on github https://github.com/shouldjs/should.js/issues
    ✓ should pass 

  should 4.2.0
WARN Strict version of eql return different result for this comparison
WARN it means that e.g { a: 10 } is equal to { a: "10" }, make sure it is expected
WARN To disable any warnings add should.warn = false
WARN If you think that is not right, raise issue on github https://github.com/shouldjs/should.js/issues
    ✓ should pass 

  should 4.2.1
WARN Strict version of eql return different result for this comparison
WARN it means that e.g { a: 10 } is equal to { a: "10" }, make sure it is expected
WARN To disable any warnings add should.warn = false
WARN If you think that is not right, raise issue on github https://github.com/shouldjs/should.js/issues
    ✓ should pass 

  should 4.3.0
    1) should pass

  should 4.3.1
    2) should pass

  should 4.4.0
    3) should pass

  should 4.4.1
    4) should pass

  should 4.4.2
    5) should pass

  should 4.4.3
    6) should pass

  should 4.4.4
    7) should pass

  4 passing (252ms)
  7 failing

  1) should 4.3.0 should pass:

      AssertionError: expected [ { CustomerRef: '123456' } ] to equal [ { CustomerRef: 123456 } ] (at '0' -> CustomerRef, A has '123456' and B has 123456)
      + expected - actual

       [
         {
      +    "CustomerRef": 123456
      -    "CustomerRef": "123456"
         }
       ]

  2) should 4.3.1 should pass:

      AssertionError: expected [ { CustomerRef: '123456' } ] to equal [ { CustomerRef: 123456 } ] (at '0' -> CustomerRef, A has '123456' and B has 123456)
      + expected - actual

       [
         {
      +    "CustomerRef": 123456
      -    "CustomerRef": "123456"
         }
       ]

  3) should 4.4.0 should pass:

      AssertionError: expected [ { CustomerRef: '123456' } ] to equal [ { CustomerRef: 123456 } ] (at '0' -> CustomerRef, A has '123456' and B has 123456)
      + expected - actual

       [
         {
      +    "CustomerRef": 123456
      -    "CustomerRef": "123456"
         }
       ]

  4) should 4.4.1 should pass:

      AssertionError: expected [ { CustomerRef: '123456' } ] to equal [ { CustomerRef: 123456 } ] (at '0' -> CustomerRef, A has '123456' and B has 123456)
      + expected - actual

       [
         {
      +    "CustomerRef": 123456
      -    "CustomerRef": "123456"
         }
       ]

  5) should 4.4.2 should pass:

      AssertionError: expected [ { CustomerRef: '123456' } ] to equal [ { CustomerRef: 123456 } ] (at '0' -> CustomerRef, A has '123456' and B has 123456)
      + expected - actual

       [
         {
      +    "CustomerRef": 123456
      -    "CustomerRef": "123456"
         }
       ]

  6) should 4.4.3 should pass:

      AssertionError: expected [ { CustomerRef: '123456' } ] to equal [ { CustomerRef: 123456 } ] (at '0' -> CustomerRef, A has '123456' and B has 123456)
      + expected - actual

       [
         {
      +    "CustomerRef": 123456
      -    "CustomerRef": "123456"
         }
       ]

  7) should 4.4.4 should pass:

      AssertionError: expected [ { CustomerRef: '123456' } ] to equal [ { CustomerRef: 123456 } ] (at '0' -> CustomerRef, A has '123456' and B has 123456)
      + expected - actual

       [
         {
      +    "CustomerRef": 123456
      -    "CustomerRef": "123456"
         }
       ]

The extension of Object breaks the behaviour of objects

first of all: Thank you very much for the great work. When I first saw should.js I was basically thunderstruck.

However, I recently stumbled upon an issue with the extension of Object.
If you have some nodejs module A requiring should, and another module B organizing A (and other requires) in an object o1, the behaviour of the keys from o is basically broken: You can print the key as a string, but you cannot reuse it as key in a new object o2.

Sorry for the bad explanation, if it's confusing I could provide you with some sample code.

Do you think there's something we can do about this? Maybe (at least) making the Object extension kind of optional?

Assert any property of an object

How can I assert an object to have one out of 2 properties?

Where res.body is an object and do so sort of like
res.body.should.have.property('error');
OR
res.body.should.have.property('code');

Could I use res.body.should.have.any.property(['error', 'code']);?

.empty not working when using should as a method

Hello,

I'm trying to upgrade to the latest version of should.js. I'm using should after deleting Object.prototype.should, because some of my object does have a property named should (and I cannot change that).

I experienced an issue on calls like this one:

should('foo').not.be.empty;

I got an error and I experienced an issue on calls like this one:Cannot read property 'have' of undefined` which is caused by should.js

I re-created the issue in a unit test here: ghusse@6ff8d36

If you run NPM test with this new test case, you get this error:

1) should as a method should correctly detect empty strings

       Cannot read property 'have' of undefined

       + expected - actual


       at Assertion.<anonymous> (lib/ext/property.js:272:22)

       271 |     if(util.length(this.obj) !== void 0) {
       272 |       this.obj.should.have.property('length', 0);
       273 |     } else {

       at Assertion.prop.(anonymous function) [as empty] (lib/assertion.js:51:12)

       50 |     try {
       51 |       func.apply(context, arguments);
       52 |     } catch(e) {

       at Context.emptyTest (test/ext/method.test.js:21:16)

       20 | function emptyTest(){
       21 |   should('').be.empty;
       22 |   should('foo').no.be.empty;

npm ERR! Test failed.  See above for more details.

Should hangs Karma (when using RequireJS?)

For a long time I thought this was a defect with Karma, which was newer to me than Should.js, but the issue finally was resolved when I removed the latter from my project.

If needed I can revert to older revision to troubleshoot, but I don't have much time for this at moment. The observable behavior was that I would kick off a karma process with file watching, and tests would run fine first time, but when I'd touch files, most of the time but not all the time, the tests would not re-run. This seemed to be an issue with karma and OS file-watching, but turned out was immediately resolved by removing Should.js. When this issue occurred, even refreshing the test run browser would refuse to execute, would hang with no output anywhere.

Sounds like a race condition (not 100% of the time, but maybe 90% of the time tests would fail like this), and though I never confirmed this, I highly suspect is specific to using RequireJS as well. Maybe Should.js is being re-initialized in some way, and doesn't play well as it modifies Object.prototype. I then read something that (I guess wrongly?) led me to believe Should.js is suitable for Node code but not expected to work well in browser.

As I recall, I had tried including 'should' as a framework in karma.conf, and tried giving it a stub: exports: clause. That doesn't seem to be supported. I tried explicitly importing into requirejs test spec modules, which seems to trigger the problem, and then not explicitly, resulting in more obvious race condition where on some runs the tests would fail as should.js had not initialized when they are loaded.

Hope that helps, I may have more time later to troubleshoot or provide a working example, but my code is not open source so I'd have to spend some time on this that I don't have at the moment.

Should conflict with my code

Copy of : tj/should.js#212 I haven't see that the repo' has moved.

In my use-case I have some objects with a property 'should' to do an ElasticSearch query, but in my tests I use should and my code failed because 'should' property already exists and don't want to be overwritten.

For example, with the lib ESQ :

boolFiltersQuery.query('bool', ['should'], 'query', 'match', name, id);

And with an abstract example code without ESQ :

var people = {};

people.should = [
  "do homework",
  "clean home"
];

console.log(people);

It displays an empty object.

How can i use a "should" property on my object while maintaining my use of the should lib?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.