GithubHelp home page GithubHelp logo

chaijs / chai Goto Github PK

View Code? Open in Web Editor NEW
8.1K 132.0 693.0 4.73 MB

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

JavaScript 99.97% TypeScript 0.03%
javascript assertions chai tdd bdd

chai's Introduction

ChaiJS
chai

Chai is a BDD / TDD assertion library for node and the browser that can be delightfully paired with any javascript testing framework.

downloads:? node:?
Join the Slack chat Join the Gitter chat OpenCollective Backers

For more information or to download plugins, view the documentation.

What is Chai?

Chai is an assertion library, similar to Node's built-in assert. It makes testing much easier by giving you lots of assertions you can run against your code.

Installation

Node.js

chai is available on npm. To install it, type:

$ npm install --save-dev chai

Browsers

You can also use it within the browser; install via npm and use the chai.js file found within the download. For example:

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

Usage

Import the library in your code, and then pick one of the styles you'd like to use - either assert, expect or should:

import { assert } from 'chai';  // Using Assert style
import { expect } from 'chai';  // Using Expect style
import { should } from 'chai';  // Using Should style

Register the chai testing style globally

import 'chai/register-assert';  // Using Assert style
import 'chai/register-expect';  // Using Expect style
import 'chai/register-should';  // Using Should style

Import assertion styles as local variables

import { assert } from 'chai';  // Using Assert style
import { expect } from 'chai';  // Using Expect style
import { should } from 'chai';  // Using Should style
should();  // Modifies `Object.prototype`

import { expect, use } from 'chai';  // Creates local variables `expect` and `use`; useful for plugin use

Usage with Mocha

mocha spec.js --require chai/register-assert.js  # Using Assert style
mocha spec.js --require chai/register-expect.js  # Using Expect style
mocha spec.js --require chai/register-should.js  # Using Should style

Read more about these styles in our docs.

Plugins

Chai offers a robust Plugin architecture for extending Chai's assertions and interfaces.

  • Need a plugin? View the official plugin list.
  • Want to build a plugin? Read the plugin api documentation.
  • Have a plugin and want it listed? Simply add the following keywords to your package.json:
    • chai-plugin
    • browser if your plugin works in the browser as well as Node.js
    • browser-only if your plugin does not work with Node.js

Related Projects

Contributing

Thank you very much for considering to contribute!

Please make sure you follow our Code Of Conduct and we also strongly recommend reading our Contributing Guide.

Here are a few issues other contributors frequently ran into when opening pull requests:

  • Please do not commit changes to the chai.js build. We do it once per release.
  • Before pushing your commits, please make sure you rebase them.

Contributors

Please see the full Contributors Graph for our list of contributors.

Core Contributors

Feel free to reach out to any of the core contributors with your questions or concerns. We will do our best to respond in a timely manner.

Jake Luer Veselin Todorov Keith Cirkel Lucas Fernandes da Costa Grant Snodgrass

chai's People

Contributors

abetomo avatar astorije avatar cmpolis avatar domenic avatar flaambe avatar greenkeeper[bot] avatar greenkeeperio-bot avatar jfirebaugh avatar jgonera avatar joliss avatar josher19 avatar joshperry avatar jsoref avatar keithamus avatar koddsson avatar leider avatar logicalparadox avatar lucasfcosta avatar meeber avatar rubenverborgh avatar scottnonnenberg avatar shvaikalesh avatar sonicdoe avatar sukrosono avatar thesavior avatar turbo87 avatar umireon avatar vesln avatar vieiralucas avatar zetamorph 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  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

chai's Issues

.throw broken?

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...?

negated property(name, value) assertion

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?

Assert max and min length of a string

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 :)

Feature request: add 'properties' assertion

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)

How Should I Throw?

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?

Provide minified version

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
});
 ^

assert.isNumber is broken

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]'

Checking `ErrorConstructor.name` is too strict

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.

Deep property equality testing?

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?

assert error objects

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.

One of assertion

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?

.property("anything.with.dots") breaks moving to Chai 1.0.

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? :-/

Allow writing JSLint/JSHint friendly tests

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.

Suggestion - chai assert page, adjust layout so all asserts show in upper left and/or top of content

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

Add `throw(error)` overload

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!

add assert.fail

would like to see an assert.fail(msg)

assert.isTrue(false, msg) is less concise.

getting Script Error in html reporter.

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

include/string/contain doc errors

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.

.throw()

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 throwwhile keepin its value, if someone finds a similar word, I would gladly do the pull request myself.

should not working in browser

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

Bug: deep.property

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]'

Uncaught TypeError: Cannot read property 'CHAI_COV' of undefined

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.

expect().to.be() not working in Chrome

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

IE problems

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.

The name property

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'

Other problems with inspect and the messages it produces

Various 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 inspected 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.

Checking `ErrorConstructor.name` does not always work

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.

http://chaijs.com/ webpage

http://chaijs.com/ has:

  1. "wrong travis link" and
  2. Contributor Jakub Nešetřil is incorrectly displayed as Jakub NeÅ¡etÅ™il
    on Chrome 15.0.874.106 on Linux. Looks okay on FireFox 10 except color is black instead of blue.
    Could be a Chrome or Codex bug.

->> Josh W <<-

Scrollbar in documentation is invisible

AKA "Hey there are like twenty assertions I didn't know about because I couldn't freaking see them"

screenshot

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.

Many tests fail on Webkit/JavaScriptCore (Safari 5.1.7, PhantomJS 1.5)

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:

expect().to.be.X() doesn't work in IE

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__ : {...}
} 

Make assertions (such as .exist) callable

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?

Improve error capturing

  • Pass actual and expected values upon construction of AssertionError so that testing libraries that check for this can report on it.
  • Make assert custom errors more useful.

Is there a "supported" way to extend the set of assertions?

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?

Is it possible to support should.exist('hello') ?

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!

Add notInstanceOf() assert

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.)

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.