chaijs / chai Goto Github PK
View Code? Open in Web Editor NEWBDD / TDD assertion framework for node.js and the browser that can be paired with any testing framework.
Home Page: https://chaijs.github.io
License: MIT License
BDD / TDD assertion framework for node.js and the browser that can be paired with any testing framework.
Home Page: https://chaijs.github.io
License: MIT License
assert.isNumber(1)
and assert.isNumber(Number)
fails,assert.isNumber(new Number(1))
works. This same issue comes up with your other type checks. You should probably use something more robust than instanceof
or typeof
, which to not cover all the cases. A solution, used by underscore.js, is:
coffee> Object.prototype.toString.call(1)
'[object Number]'
coffee> Object.prototype.toString.call(Number(1))
'[object Number]'
coffee> Object.prototype.toString.call(new Number(1))
'[object Number]'
expectjs now checks for empty objects (i.e. they have no keys)
I think this is more useful
There's assert.isUndefined,
But no assert.isDefined
I might be doing something wrong. But I'm getting a "Script error" when my assertions fail.
Here are my specs
https://gist.github.com/1497704
I'm getting the following error in the development console:
Uncaught AssertionError: expected [ { code: '026',
description: 'Resource not found.',
httpCode: 404 } ] to be empty
This works with expect.js:
expect(true).to.be(true);
But with chai.js in the browser (Chrome), I get:
TypeError: Property 'be' of object #<Assertion> is not a function
Hello,
We are using chai.js
with mocha
and we run our tests in the browser...
It looks like a recent version of Chai introduced a little bug: Uncaught TypeError: Cannot read property 'CHAI_COV' of undefined
.
It looks like it's coming from the fact that you now use process.env.CHAI_COV to load the appropriate library... and process.env does not seem to exist in the browser.
throw
is a reserved word in Javascript, so it's quite normal for linters (jslint, jshint....) to emit warnings like Expected an identifier and instead saw 'throw' (a reserved word).
In fact, during tests, Internet Explorer 7, at least, breaks due that same error.
Note: I would fork and do a pull request, however english is not my first language, and I can't find a similar word to replace throw
while keepin its value, if someone finds a similar word, I would gladly do the pull request myself.
http://chaijs.com/ has:
->> Josh W <<-
defineProperty is not compatible with pre-IE9
/cc @kevindente
Could assertions for upper-/lowercase be added?
expect('string').to.be.uppercase()
expect('string').to.be.lowercase()
I have a string that needs to be either "new", "used" or "refurbished".
Is there a way to assert that it's one of these?
I have a function that is passing an error object to it's callback:
function createUser (callback) {
callback(new Error('user exists'));
}
createUser(function (err) {
expect(err.message).to.equal('user exists')
});
I need to assert that the error is passed.
Is that the best way to do this?
Feel hacky in a way.
The include
API doc has this example
expect([1,2,3]).to.contain(2);
I think that's meant to be:
expect([1,2,3]).to.include(2);
string
has this example:
expect('foobar').to.include.string('bar');
I think that's meant to be:
expect('foobar').to.have.string('bar');
Though, if you did want include
to work as both a function and a chaining property, it seems to be possible:
Object.defineProperty(Assertion.prototype, 'include', {
get: function () {
var include = function (obj) {
this.assert(
~this.obj.indexOf(obj)
, 'expected ' + this.inspect + ' to include ' + inspect(obj)
, 'expected ' + this.inspect + ' to not include ' + inspect(obj));
return this;
};
include.__proto__ = this;
return include;
}
});
I think it would be nice if both include
and contain
worked this way (i.e. they were synonyms, with the definition above):
expect([1,2,3]).to.contain(2);
expect([1,2,3]).to.include(2);
expect('foobar').to.contain('bar');
expect('foobar').to.include('bar');
expect({foo: 1, bar: 2}).to.contain.keys('foo', 'bar');
expect({foo: 1, bar: 2}).to.include.keys('foo', 'bar');
I can send a pull request if you agree.
would like to see an assert.fail(msg)
assert.isTrue(false, msg) is less concise.
I just switched to chai from expect.js (because I like the sinon-chai plugin) and was expecting (no pun intended) to be able to match thrown error messages against particular strings.
I've found I have to do something like...
( expect try
Obj.method()
catch error
error.message
).to.equal 'expected string'
I'm using the latest version of chai and NodeJS v0.6.11, and I cannot get that behavior if I do something like:
( expect -> Obj.method() ).to.throw 'expected string'
-- or --
( expect -> Obj.method() ).to.throw Error, 'expected string'
Both of those will pass with flying colors even if the string does not match the actual error message. Is something broken, or do I have the wrong idea or...?
I have recently written a few tests like this:
serverRequest.should.have.property("customerId", "abc");
serverRequest.should.have.property("clientId", "123");
serverRequest.should.have.property("scope");
serverRequest.scope.should.deep.equal(["foo", "bar"]);
Those last two lines are sad, but necessary since property
does strict equality testing.
I was thinking maybe we should add a third boolean argument to property
, that will do deep equality if true? Then it'd be
serverRequest.should.have.property("customerId", "abc");
serverRequest.should.have.property("clientId", "123");
serverRequest.should.have.property("scope", ["foo", "bar"], true);
I guess this is also a case for the properties
assertion of #72, heh.
Thoughts?
When using expect() for writing asserting, some of the assertion are using properties as the mean for calling assert.
For example
expect(foo).to.exist
JSLint/JSHint will complain about such code, since it expects an assignment or function call.
Hiding a function call, behind getting a property can be sweet but in tests, it leads to such warnings.
I know that one can use assert calls, or not use JSHint/JSLint or configure JSHint/JSLint to ignore such warnings, but I just want to know what is your feeling about this problem.
See https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Object/DefineGetter
You can use defineProperty
or defineProperties
instead.
https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Object/defineProperty
https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Object/defineProperties
In my opinion, the fact that throws
checks against ErrorConstructor.name
is too strict. My expectation from other frameworks is that a simple instanceof
check is performed.
Removing this check would also solve the biggest problem with GH-45, namely that stuff like
myFunc.should.throw(restify.NotFoundError)
never works, since restify.NotFoundError.name === ""
and thus the assert always fails. Then GH-45 would simply be about how to get a good name for the message.
Again, happy to send a pull request if you agree.
I was hoping to make a sinon adapter for chai. This would allow code like
var spy = sinon.spy();
expect(spy).to.have.been.calledWith(1, 2, 3);
spy.should.not.have.been.called;
Unfortunately, the only way I could see to do this is to muck around with the undocumented parts of chai, by modifying require("chai").Assertion.prototype
.
Is this the best way? If so, could you document Assertion.prototype
and promise that it will be maintained as a supported extension point as long as the major version number stays the same?
Hi thks for the lib
just notice this typo in the doc
instanceof instead of instanceOf
There are some API changes in should.js 0.4.x (https://github.com/visionmedia/should.js/commits/master).
I tried to write should.js
style throw statements like so (new Bill(input)).should.throw(Error);
but its not working. Where can I find resources wherein I can checkout documentation on should assertion style?
I would expect a negated assertion to pass if and only if it would fail if not negated. But this is not true of the property(name, value)
assertion:
expect('asd').to.have.property('foo', 3); // fails
expect('asd').not.to.have.property('foo', 3); // also fails (I would expect it to pass)
I realize the test verify the existing behavior, but is there any chance it could change?
@vesln per our discussions
Many of the assertion methods have an opposite equivalent equal/notEqual, strictEqual/notStrictEqual but several do not, including instanceOf
.
I'd like to see a notInstanceOf(obj, ctor, message)
assertion method.
You may want to add one for all of the other assertions (e.g. notTypeOf()
, isNotArray()
, etc.)
Official documentation points to an online suite that doesn't seem to exist:
http://chaijs.com/guide/installation/
Points to:
http://chaijs.com/support/tests/
I found this working link:
And it fails on IE9.
In firebug:
var should = chai.should() //actually call the the function
, foo = 'bar';
foo.should.be.a('string');
foo.should.equal('bar');
foo.should.have.length(3);
AssertionError: expected { '0': 'b', '1': 'a', '2': 'r' } to be a string
I tried to do it myself, but got some errors in Closure Compiler:
JSC_PARSE_ERROR: Parse error. missing name after . operator at line 2014 character 14
assert.throws = function (fn, type, msg) {
^
JSC_PARSE_ERROR: Parse error. missing ; before statement at line 2015 character 31
if ('string' === typeof type) {
^
JSC_PARSE_ERROR: Parse error. syntax error at line 2016 character 6
msg = type;
^
JSC_PARSE_ERROR: Parse error. missing ) after argument list at line 2021 character 2
};
^
JSC_PARSE_ERROR: Parse error. missing ) after argument list at line 2093 character 2
};
^
JSC_PARSE_ERROR: Parse error. syntax error at line 2095 character 1
}); // module: interface/assert.js
^
JSC_PARSE_ERROR: Parse error. invalid return at line 3119 character 7
return require('chai');
^
JSC_PARSE_ERROR: Parse error. syntax error at line 3120 character 1
});
^
The problem lies in addChainableMethod
. For some reason (probably a JavaScriptCore bug) you cannot get property descriptors of Function.prototype
(you always get undefined), so this check never gets trigerred and it tries to redefine the arguments
property.
The curious thing is that the arguments
property is defined in the Assertion
and, in theory, is configurable. However, it seems that some built-in JavaScriptCore checks always forbid changing it.
Is redefining properties really necessary for plugins to work correctly? Why is it necessary? Isn't this a bit shaky since you can't (don't want to) redefine the arguments
property anyway? And why does it get invoked every time the property is used in a test and not after registering a plugin?
If it's impossible to replace redefining properties with something else, I think the easiest solution for now would be to add a simple check for JavaScriptCore:
if (
(functionProtoPD && !functionProtoPD.configurable) ||
asserterName === 'arguments'
) {
return;
}
Edit: This is a recent regression introduced in 1.0.2 by these two commits:
Includes:
We had the following assertion:
expect(httpResponse).to.have.property("http://example.com/documents")
This is now broken with Chai 1.0, I assume because it's looking for a property http://example
which in turn has a property com/documents
.
Any ideas on what the right fix is? :-/
IE claims that the expect().to.be
object has no method 'below', 'above', etc. The 'be' object seems to be defined as:
function (selector) {
var obj = flag(this, 'object');
if (obj instanceof jQuery) {
this.assert(
obj.is(selector)
, 'expected #{this} to be #{exp}'
, 'expected #{this} not to be #{exp}'
{
__proto__ : {...}
}
According to the doc we should be able to do this:
var expect = require('chai').expect;
var object = {
data: [
[true]
]
};
expect(object).to.have.deep.property('data[0][0]', true);
But this gives error:
expected { data: [ [ true ] ] } to have a deep property 'data[0][0]'
node v0.8.0
It doesn't seem to be a way asserting that a string has a min/max length.
That would be great validations before the data gets into the database.
Eg.
expect('Logitech Navigator').to.have.a.min.length.of(3)
expect('Logitech Navigator').to.have.a.max.length.of(20)
What do you think?
EDIT:
Forgot I could just do:
expect('Logitech Navigator'.length).to.be.above(3)
expect('Logitech Navigator'.length).to.be.below(20)
Feel free to close this issue :)
actual
and expected
values upon construction of AssertionError so that testing libraries that check for this can report on it.Chai's throw
checks ErrorConstructor.name
against the thrown error, and uses it in the assertion output.
This is incompatible with dynamically-constructed errors, e.g. those from Restify, since the constructors there don't have a name
property. (See also proposed solution on Restify's side using eval
.)
We can fix this in the case of some libraries by testing against ErrorConstructor.prototype.name
, but note that not all custom errors properly set up the prototype. (In particular, Restify before my pull request sets it on the instances only.) A more bulletproof, but kind of inelegant, fix would be to construct a new instance of the error simply to inspect its name property:
var dummyError = new constructor();
var name = dummyError.name;
Thoughts? I'd be happy to send a pull request for either approach if desired.
There's a pretty common case that the existing deep.equal, deep.property, and contains.keys APIs don't cover, namely asserting that an object should have some properties of some given values. Namely, I'd like to be able to say:
obj = {...};
expect(obj).to.have.properties({
a: 42,
b: "someVal"
});
obj is allowed to have other properties as well, but fails if a or b is absent or has a different value.
Here's the coffeescript I hacked up to do this locally, which barely works:
chai.Assertion.addMethod 'properties', (expectedPropertiesObj) ->
args = ([key,val] for own key,val of expectedPropertiesObj)
args = _.flatten(args)
this.property.apply(this, args)
IE10 refuses to run while the document is in quirks mode. So first, that needs to be fixed, by adding <!DOCTYPE html>
to index.html.
After that, here are the problems I am discovering on IE10 developer preview (10.0.8102.0). There are lots of them, somewhat surprisingly given its excellence at test-262.
Chai uses the name
property in its assertion messages, which functions do not have in IE. Thus you get lots of failures like
AssertionError: expected 'expected 3 to be an instance of Foo' to equal 'expected 3 to be an instance of undefined'
inspect
and the messages it producesVarious other tricks that inspect
is doing fail:
AssertionError: expected 'expected 'asd' to have a property 'constructor' of [Function: Number], but got [Function: String]' to equal 'expected 'asd' to have a property 'constructor' of [Function], but got [Function]'
typeof this === "object"
for numbers.This one's wierd.
When using should
, numbers get inspect
ed as "{}"
. E.g. typing this in the console:
(0).should.not.be.ok
gives the assertion error expected {} to be falsy
. This in turn is because (0).should.inspect === "{}"
, which is because `typeof (0).should.obj === "object".
Here's the problem: inside the getter for Object.prototype.should
, typeof this === "object"
and also this instanceof Number === false
. This seems like an IE bug or perhaps a place the spec isn't clear enough in. Fascinating... and evil.
Reproduced at this JSFiddle: Firefox says nothing (?), Chrome says number
, IE says object
.
AKA "Hey there are like twenty assertions I didn't know about because I couldn't freaking see them"
As you can see in the screenshot on Chrome/Mac, there is absolutely no indication that that list is scrollable. I was kind of bummed that Chai included so few assertions out of the box, before I accidentally scrolled this list.
assert.operator(0, '>', 0, "see some things")
observed:
see some things: expected false to be true
expected:
see some things: expected 0 to be > 0
I'm hotlinking to http://chaijs.com/chai.js. I was hoping the following should syntax from visionmedia/shouldjs would be supported, since I'd like to avoid using expect() if possible:
should.exist('hello')
should.exist([])
should.exist(null) // will throw
If it is supported, it's not working for me for some reason, I get "Type error".
Thanks!
I am currently writing some tests using the expect-version of chai. And it is going fine, except there is a readability issue.
Take the following code:
expect(someVariable).to.exist;
This is perfectly valid, and will test as expected, since the assertion is done inside the getter .exist
.
But to my eye, there is no action taken here. I would much prefer the line to be:
expect(someVariable).to.exist();
This can be achieved by simply changing the .exist
definition from:
Object.defineProperty(Assertion.prototype, 'exist',
{ get: function () {
this.assert(
null != flag(this, 'object')
, 'expected #{this} to exist'
, 'expected #{this} to not exist'
);
return this;
}
, configurable: true
});
to:
Object.defineProperty(Assertion.prototype, 'exist',
{ get: function () {
this.assert(
null != flag(this, 'object')
, 'expected #{this} to exist'
, 'expected #{this} to not exist'
);
var self = this;
return function() { return self; };
}
, configurable: true
});
The only drawback is that you cannot chain directly on .exist
(like expect(a).to.exist.ok
), but since there is no .and
and the tests does not break after doing the change above, I don't see that as an issue.
So the question is, is this only an issue in my mind? And should I spend time on making a proper pull request?
throw
already accepts an error constructor plus, optionally, an error substring or regex matcher. But it's not enough!! :)
I find myself often doing the following, to test that errors are re-thrown correctly:
var fakeError = new TypeError("boo!");
beforeEach(function () {
thingBeingStubbed.someMethod = function () { throw fakeError; };
});
it("should rethrow the error", function () {
systemUnderTest.methodUsingStubbedThing.should.throw(fakeError.constructor, fakeError.message);
});
Instead I'd like to be able to do just
systemUnderTest.methodUsingStubbedThing.should.throw(fakeError);
This should be backward-compatible: we test if the param is instanceof Error
, and if so go down this new code path.
Thoughts? If you like it, a pull request will be on the way!
There are currently no documentation for:
should.equal();
should.throw();
should.exist();
And negated versions.
On the chai assert page, they layout of the upper left box with the list of asserts does not show all of the asserts and also doesn't show any scroll bars (on Mac Lion) so people don't know there are actually many more asserts than what is visible.
Many members of my team were not aware of the other asserts available because of this layout issue. It isn't obvious that there are more asserts.
It should be easy to work around this, by either extending the size and/or listing all of the asserts on the top of the content itself.
If people aren't aware of these other asserts, they will think the library is much more limited than it really is, chai has a wonderful group of asserts and is the only assert framework to work in both browser and server, so I want it to thrive.
Thanks,
Jeff
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.