domenic / chai-as-promised Goto Github PK
View Code? Open in Web Editor NEWExtends Chai with assertions about promises.
License: Other
Extends Chai with assertions about promises.
License: Other
Right now I find myself doing a lot of this:
promise().then(function () {
state.should.have.changed;
}).should.be.fulfilled.notify(done);
This is a bit awkward, both grammatically and because if state.should.have.changed
fails, you get as your error "expected promise to be fulfilled but instead it was rejected with AssertionError
." Ideally, you want the actual assertion error, just like if you had written synchronous code.
One solution, I think, would be some syntax like
promise().should.be.fulfilled.then(function () {
state.should.have.changed;
}).should.notify(done);
This will give an "expected promise to be fulfilled" error only if the original promise was rejected, whereas, because it's not passing through the .should.be.fulfilled
chain, the failure of state.should.have.changed
would pass the original AssertionError
up to the test runner, instead of wrapping it in a "should have been fulfilled but instead got AssertionError
" message.
Using
1.0.1
1.9.1
4.1.1
I can run the following code, everything passes...and I'm quite confused.
var q = require('q'),
chai = require('chai'),
expect = chai.expect;
// dependencies & test lib configuration
chai.use(require('sinon-chai'));
chai.use(require('chai-as-promised'));
describe('pls work', function() {
it('does not seem to work :(', function() {
// this does not make sense to me
expect(q.resolve('foo').thenReject('baz')).to.eventually.be.fulfilled;
// same here
expect(q.resolve('foo').thenResolve('baz')).to.eventually.be.rejected;
var defer = q.defer();
defer.reject('bar');
defer.promise.done(null, function(err) {
console.log('huh?');
return false;
});
// state: rejected ...?
console.log(defer.promise.inspect());
// what am I doing wrong?
expect(defer.promise).to.eventually.be.fulfilled;
var blah = function(thing) {
return thing;
},
obj = {
bleh: function() {
var defer = q.defer();
q.resolve('foo')
.then(blah)
.then(function(woo) {
defer.resolve(woo);
})
.done();
return defer.promise;
},
};
// I'm going nuts.
expect(obj.bleh()).to.eventually.be.rejected;
});
});
Is there anything that I am blatantly doing wrong?
Thanks in advance!
Hi there,
I tried to work with chai-as-promised
in order to open an issue related to this discussion. Before I could come up with anything on that topic, though, I tried to run the tests on my fresh clone and… some fail.
So, to recap:
$ git clone [email protected]:domenic/chai-as-promised.git
$ npm install .
$ npm test
> ✖ 5 of 157 tests failed
All complain that Object [object Function] has no method 'apply'
(yup…).
Is this supposed to be normal?
Regards,
Matti
I have a question that deals with .notify(). I wasn't sure the best place to post it. If you want I can move it over to Stackoverflow.
I'm using Protractor, cucumberjs, chai & chai-as-promised. We've been changing around our code and now running into issues of test runs just stopping completely without a reason why, which is an issue with Protractor or cucumber.
I'm aware that chai-as-promises uses the Promises/A+ specification, so we do something like this.
var promise = element(by.css('.pass')).isDisplayed();
expect(promise).to.eventually.to.equal(true, "Link should be displayed').and.notify(next);
1st Question -
If we have 2 steps in a scenario, should / can they both have notify(next) in them. I thought notify next was used to signal the next scenario to start.
I thought it need to be structured like so
Scenario 1
Step 1 (expect(p).to.eventually.to.equal(true).and.notify(next);)
Step 2 (expect(p2).to.eventually.to.equal(false).and.notify(next);)
Scenario 2
.......
Or should it be like
Scenario 1
Step 1 (expect(p).to.eventually.to.equal(true);)
Step 2 (expect(p2).to.eventually.to.equal(false).and.notify(next);)
Scenario 2
.......
Question 2 -
I was looking through http://chaijs.com/plugins/chai-as-promised and saw that you are calling notify on the should of then's.
promise.should.be.fulfilled.then(function () {
expect(p).to.eventually.to.equal(true)
otherState.should.equal("after");
}).should.notify(done);
I'm assuming that chai-as-promised can call notify with-in the then with out issues. (FYI - when the expect(p) fails, this halts the test run with no indication with what failed)
promise.should.be.fulfilled.then(function () {
expect(p).to.eventually.to.equal(true)
should.equal("after").should.notify(done);
otherState.should.equal("after").should.notify(done);
});
Question 3 -
We need to verify that many elements are set so we do something like this. I believe this is wrong because .notify() is being called for each iteration.
var divs = element.all(by.css('div.wrapper')); // gets all divs with wrapper class
divs.each(function(div){
expect(div.element(by.css('.title')).getText()).to.eventually.to.equal('A title');
expect(div.element(by.css('.error')).getText()).to.eventually.to.equal('An Error').and.notify(done);
});
Instead we should do something like this. We can't call should notify directly off the then because it's a protractor promise. I was thinking of a way to use Q.all([]) but I don't there's a clean way to do it.
var divs = element.all(by.css('div.wrapper')); // gets all divs with wrapper class
divs.each(function(div){
expect(div.element(by.css('.title')).getText()).to.eventually.to.equal('A title');
expect(div.element(by.css('.error')).getText()).to.eventually.to.equal('An Error');
}).then(function(){
"1".should.equal("1").should.notify(done);
})
Like I said earlier, if this isn't the place to post this, I'll move it over to stack overflow.
In the following code, the two test cases should fail. However, they pass.
var chai = require('chai');
var chaiAsPromised = require('chai-as-promised');
chai.use(chaiAsPromised);
var assert = chai.assert;
var Q = require('q');
describe('Chai-test', function () {
it('Should fail if rejected with no value ', function () {
var promise = Q.reject();
return assert.becomes(promise,2);
});
it('Should fail if rejected with no value (eventually.equal)', function () {
var promise = Q.reject();
return assert.eventually.equal(promise,2);
});
});
Howdy! In writing some tests for code using https://github.com/tildeio/rsvp.js, we've run into unexpected behavior. The fulfilled
assertion helper is always passing, regardless of if the promise is actually rejected.
Promises in RSVP are deferred in different ways depending on your env. In Node, they are deferred with nextTick
. In Firefox and Webkit with MutationObserver
and a disconnected DOM node. In all other envs with setTimeout
. See https://github.com/tildeio/rsvp.js/blob/master/lib/rsvp.js#L3 for detail.
This deferral means sinon's normal fake timers don't force the code to be synchronous. I was hoping this is the problem chai-as-promised was addressing. Here is a fiddle of chai-as-promised allowing an assertion that should be false:
I wanted to write sth like:
getPromiseSomehow({oh:'this is bad arg').should.be.rejectedWith({
status: 400,
name: 'you messed up arg'
});
I'd like chai to check whether rejection reason has these guys with these values. Is that possible? If not, does it make sense?
I am able to navigate to a url before a test but not during. this simple example locks up consistently for me after 'getting google'....
it('should fulfill a promise then navigate to a url', function() {
var myPromise = function() {
var defer = q.defer();
defer.resolve();
return defer.promise;
};
return myPromise().then(function() {
console.log('getting google');
return browser.driver.get('http://www.google.com/');
}).then(function() {
console.log('loaded google!');
});
});
not sure if this is a bug or i am using it wrong.
I and @llun discovered that when .eventually.equal assertion fail, the actual
property is the promise, instead of the value returned by the promise.
Here is an example run in the REPL that demonstrates this problem:
> var chai = require('chai')
> chai.use(require('chai-as-promised'))
> var q = require('q')
> chai.should()
> var r = q.resolve(555).should.eventually.equal(3)
// this assertion should return a rejected promise
> var e
> r.fail(function(err) { e = err })
> e
{ message: 'expected 555 to equal 3',
actual:
{ ... /* the promise object */ },
expected: 3,
operator: undefined,
showDiff: true }
Here the actual
property should be 555, instead of the promise.
Mocha used this property to show a diff between the actual/expected value. With this bug mocha reports the actual value as {}
instead.
Sorry, this is probably just a case of me not entirely understanding how to use this correctly, but I've noticed that this library doesn't seem to work without still using the done
function and chaining notify
, even on the latest version of mocha which supposedly has promise support. Example:
describe 'test', ->
it 'works without notify', ->
W.resolve('foo').should.eventually.equal('bar')
# => this test passes
it 'works with notify', (done) ->
W.resolve('foo').should.eventually.equal('bar').notify(done)
# => this one fails
Here I'm using when.js to create the resolved promises.
Relevant versions of dependencies:
And finally, if it helps, the full project that I used to produce this test case: http://cl.ly/V2Et
I'm using this with Cucumber.js, which requires a callback to be called after each test runs.
We basically want to do this:
expect(someElement.getText()).to.eventually.equal('foo').then(function () { callback(); }, function(failure) { callback(failure); });
We originally used the expect() syntax. However, this appears to return the original promise from protractor (or some variation of it). Since this promise is already resolved, it can't be rejected if the test fails. This has caused caused a lot of flakiness in our tests when they fail. (They tend to just hang.)
Recently we tried the assert() syntax. This appears to return a new promise (unless an error message is specified ??? - in which case it throws an exception). This new promise is rejected if the assertion fails.
Should these do the same thing? Is there a way to force expect() to return a new promise that is resolved or rejected based on the outcome of the expectation?
Chained promises like this does not work:
fn = path.join __dirname,'../../text.txt'
someText = 'Too legit, too legit to quit.'
p = Q.nfcall fs.writeFile,fn,someText
p.then( ->
Q.nfcall fs.readFile,fn
).then((data) ->
assert data.toString() is someText #just be ignored
,(err) ->
console.log err
).done()
assert.isFulfilled p
I have to change test case as follows to make it run:
fn = path.join __dirname,'../../text.txt'
someText = 'Too legit, too legit to quit.'
p = Q.nfcall fs.writeFile,fn,someText
p2 = p.then( ->
Q.nfcall fs.readFile,fn
)
p2.then((data) ->
assert data.toString() is someText
,(err) ->
console.log err
).done()
assert.isFulfilled p
assert.isFulfilled p2
I'm new to chai, but I'm trying to assert an array will eventually have a thing in it...
ex:
(mocha btw)
describe("test", function(){
it("will work with a promise", function(done){
var thing = [1, 2, "the];
//fails:
expect(thing).to.eventually.contain(2);
//also fails:
expect(thing).to.eventually.contain(2).notify(done);
//passes (because this isn't async)
expect(thing).to.contain(2);
});
it("promises test", function(done){
var asyncthing = setTimeout(function(done){
return ["another thing!", "word"];
}, 500);
expect(asyncthing).to.eventually.contain("word");
});
});
In fact, it does not set a this object at all, which causes errors for instance in
Assertion.addProperty('ok', function () {
this.assert(
flag(this, 'object')
, 'expected #{this} to be truthy'
, 'expected #{this} to be falsy');
});
Where this.assert is undefined.
isChainableMethod = typeof propertyDesc.get.call(this, {}) === "function"
Using chai 1.9.1
Could this example be rewritten with expect
instead of should
?
it("should change the state", function (done) {
otherState.should.equal("before");
promise.should.be.fulfilled.then(function () {
otherState.should.equal("after");
}).should.notify(done);
});
for whenjs, expectation like:
@defer.should.be.rejected.with("error")
fails with exception TypeError: Cannot call method 'indexOf'' of undefined
Chai as Promised seems to perform very slow, even after a promise has been resolved:
describe "The promise", ->
it "should eventually be string", ->
Q.delay('x', 10).should.eventually.be.a('string')
it "should eventually be string", ->
Q.delay('x', 10).should.eventually.be.a('string') for x in [1..20
results in
The array promise
✓ should eventually be string (48ms)
✓ should eventually be string (4763ms)
Full code in this gist.
I expect the second test to take more or less the same time as the first, since time should be dedicated to checking 200 times whether 'x '
is a string.
Hi,
Not really an issue, but more so a question - apologies if not appropriate here (maybe should be on stackoverflow).
I've just started to implement chai-as-promised
in a few places in my mocha test suites and it's working out very well.
I have this case in a few tests where I need to restore a sinon stub.
I've tinkered a little but I'm not sure if chai-as-promises can handle this use case?
utilsArticles.count(req)
.then(function () {
// no success
},
function (err) {
err.should.match(/unable/);
})
.finally(function () {
mongoose.Model.count.restore();
done();
})
.done();
My code style preference is to use .done()
unless I need to return and I also
put the mocha done()
call in all promise tests in finally() just so it's uniform.
Am I able to use chai-as-promised
in the above test or best to leave this type in the more verbose style?
Thanks!
See http://stackoverflow.com/questions/24019234/using-chai-as-promised-in-protractor
works:
browser.driver.getTitle().then(function(title){
title.should.eql('something');
});
doesn't work:
browser.driver.getTitle().should.eventually.eql('something');
The following code snippet fails when run in Mocha:
chai = require 'chai'
cap = require 'chai-as-promised'
chai.use cap
P = require 'node-promise'
expect = require('chai').expect
it "should succeed but it fails", (done)->
foo = ->
def = P.defer()
def.resolve a:b:2
return def.promise
expect(foo()).to.eventually.have.deep.property('a.b').notify(done)
I am getting "expected { a: { b: 2 } } to have a property 'a.b'". When I try
expect(a:b:2).to.have.deep.property("a.b")
it works fine.
Q promises (Kriskowal) fail as well.
I'm using chai-as-promised + mocha for writing some selenium-webdriver tests. Since webdriver extensively uses promises, I imagined it would be better if I used chai-as-promised for those type of tests.
The problem is that when the tests fail, the error is not being caught properly by mocha, and it just fails without outputting anything.
Sample code:
it 'tests log', (next) ->
log = @client.findElement(By.css("..."))
Q.all([
expect(log.getText()).to.eventually.equal("My Text")
expect(log.findElement(By.css(".image")).getAttribute('src'))
.to.eventually.equal("/test.png")
]).should.notify(next)
According to documented behaviour, chai-as-promised should pass the errors along to mocha when the expectation fails. Right?
As a variation,
I've also tried these, but to no avail:
2nd Try (same, no error on failure)
it 'tests log', (next) ->
log = @client.findElement(By.css("..."))
Q.all([
expect(log.getText()).to.eventually.equal("My Text")
expect(log.findElement(By.css(".image")).getAttribute('src'))
.to.eventually.equal("/test.png")
]).should.notify(next)
3rd Try (same, no error shown on failure)
it 'tests log', (next) ->
log = @client.findElement(By.css("..."))
expect(log.getText()).to.eventually.equal("My Text")
.then ->
expect(log.findElement(By.css(".image")).getAttribute('src'))
.to.eventually.equal("/test.png").should.notify(next)
4th try (DOES NOT EVEN PASS)
it 'tests log', (next) ->
log = @client.findElement(By.css("..."))
Q.all([
expect(log.getText()).to.eventually.equal("My Text")
expect(log.findElement(By.css(".image")).getAttribute('src'))
.to.eventually.equal("/test.png")
])
.then ->
next()
.fail (err) ->
console.log(err)
.done()
Right now, I'm using this to show the assertion errors. It's a nasty looking workaround. Can you please help?
it 'tests log', (next) ->
log = @client.findElement(By.css("..."))
Q.all([
expect(log.getText()).to.eventually.equal("My Text")
expect(log.findElement(By.css(".image")).getAttribute('src'))
.to.eventually.equal("/test.png")
]).should.notify((err) ->
console.log err if err # <-- this line does the trick
next(err)
)
When I have the following test:
it 'rejects the promise', (done) ->
def = Q.defer()
def.reject('raise error')
def.promise.should.be.rejected.and.notify(done)
When I run the suite using rake konacha:run
the test fails, stating "TypeError: 'undefined' is not a function". When I run the test in the browser, it passes.
I don't know where in the test it fails but it looks like the keyword rejected
has something to do with it. In a test where I test should.become(@something)
it passes in the CLI and in the browser.
So chai-as-promised seems to be loaded correctly.
Any hints what the cause of this failure on the CLI could be?
I was using chai-as-promised to do some chaining like this:
browser
.init({browserName:'chrome'})
.get("http://admc.io/wd/test-pages/guinea-pig.html")
.title()
.should.become('I am a page title - Sauce Labs')
.elementById('i am a link')
.click()
.eval("window.location.href")
.should.eventually.include('guinea-pig2')
.fin(function() { return browser.quit(); })
.done();
(see wd project)
It was working fine before 4.0, cause the input and output promise were the same, but now the chain broken cause all there is is a then
method.
Now I understand why the 4.0 rewrite is simpler, but it would be good to be able to enrich the output. For example if you are using Q promise, and you cannot do something like this, it does not feel right.
var promise = Q.fcall(function() {return "1234";});
promise.should.become('1234').done();
In chai,
actual.should.deep.equal(['A', 'B'])
works as expected,
but in chai-as-promised,
actualPromise.should.eventually.deep.equal(['A', 'B'])
is never rejected
Is this a bug?
Thanks for writing chai-as-promised. With mocha-as-promised, it has simplified most of the tests I write.
Hi, I'm using chai and i'd like to use chai as promised as i use promises in my code ;)
When i include the chai-as-promised.js it fails at
else {
// Other environment (usually <script> tag): plug in to global chai instance directly.
chai.use(chaiAsPromised);
}
as the call
function chaiAsPromised(chai, utils)
utis is undefined, so at the end
function property(name, asserter) {
utils.addProperty(Assertion.prototype, name, function () {
throws an undefined exception
[I'm using last version of chai] I thought i was using last version of chai, that was the problem!
With last version is ok :)
Thanks
I'm trying to use chai-as-promised. However I always get errors on the be property because should is undefined. I'm using q as promise library.
Part of testcase:
'use strict';
var sinon = require('sinon'),
sinonChai = require('sinon-chai'),
chaiAsPromised = require("chai-as-promised"),
chai = require('chai'),
should = chai.should(),
expect = chai.expect,
config = require('./../lib/modules/configuration'),
Configuration = config.Configuration;
chai.Assertion.includeStack = true;
chai.use(chaiAsPromised);
chai.use(sinonChai);
beforeEach(function() {
module.sinon = sinon.sandbox.create();
});
afterEach(function(){
module.sinon.restore();
});
describe('loading a non existing configuration', function () {
var configPromise;
before(function () {
var configuration = new Configuration('failing/path/');
configPromise = configuration.load();
});
it('should result in an error', function () {
//this succeeds
configPromise.then(null, function (err) {
expect(err).to.exist;
});
//this fails with the error
configPromise.should.be.rejected.and.notify(done);
});
after(function () {
config.reset();
});
});
The error:
TypeError: Cannot read property 'be' of undefined
at Context.<anonymous> (/myproj/spec/configuration.spec.js:25:29)
at Test.Runnable.run (/myproj/node_modules/grunt-mocha-chai-sinon/node_modules/mocha/lib/runnable.js:211:32)
at Runner.runTest (/myproj/node_modules/grunt-mocha-chai-sinon/node_modules/mocha/lib/runner.js:358:10)
at /myproj/node_modules/grunt-mocha-chai-sinon/node_modules/mocha/lib/runner.js:404:12
at next (/myproj/node_modules/grunt-mocha-chai-sinon/node_modules/mocha/lib/runner.js:284:14)
at /myproj/node_modules/grunt-mocha-chai-sinon/node_modules/mocha/lib/runner.js:293:7
at next (/myproj/node_modules/grunt-mocha-chai-sinon/node_modules/mocha/lib/runner.js:237:23)
at Object._onImmediate (/myproj/node_modules/grunt-mocha-chai-sinon/node_modules/mocha/lib/runner.js:261:5)
at processImmediate [as _immediateCallback] (timers.js:330:15)
Spurred by the following snipppets from emails from @RubenVerborgh:
The following should work:
Q.resolve([ { a: 1 }, { b: 2 } ]).should.eventually
.contain.something.that.deep.equals({ a: 1 });
but it doesn’t, and fails with the following message:
expected [ { a: 1 }, { b: 2 } ] to deeply equal { a: 1 }
This indicates that Chai as Promised somehow bypasses Chai Things, because the expected error message in case of failure is:
expected an element of [ { a: 1 }, { b: 2 } ] to deeply equal { a: 2 }
In other words, Chai as Promised acts like the assertion is
Q.resolve([ { a: 1 }, { b: 2 } ]).should.eventually.deep.equal({ a: 1 })
which of course fails.
Clearly, one of our two libraries is failing, and seen your amount of experience with Chai and promises, it’s probably mine :-) However, debugging tells me that Chai as Promised completely skips my promise
property.
Could you help me shed some light on this? I’ve created a gist for experimenting.
Probably the problems stem from the fact that both libraries are using a similar mechanism, e.g., providing modified versions of the basic assertion methods. I think that Chai as Promised takes it a little too far by also (and thus again) modifying the methods returned by my promise
object, but that’s just my two cents.
After a night’s sleep, I realized that rewriting Chai Things to function using flags rather than by returning modified Assertion objects could change things. And it did.
What didn’t work with the previous version now works as it should.
This leaves me with two (minor) open questions:
Assertion
objects? I think the problem is in recursively calling makeAssertionPromise
, which changes the chained method to the CaP-overriden version of the original Assertion
object every time (as opposed to modifying the methods of the currently returned assertion object).This would likely also help with performance per #14.
With plain Chai, if I do:
expect(function () {
throw new Error();
}).to.throw(Array);
I get:
AssertionError: expected [Function] to throw 'Array' but 'Error' was thrown
With Chai as Promised, if I do the equivalent:
var d = Q.defer();
d.reject(new Error());
return expect(d.promise).to.eventually.be.rejectedWith(Array);
I get:
AssertionError: expected promise to be rejected with undefined but it was rejected with [Error]
Chai as Promised thinks that the Array
constructor’s name is undefined
.
I had a brief look into this: https://github.com/domenic/chai-as-promised/blob/d607a914ea8cff473f179becf8029a241ed011ee/lib/chai-as-promised.js#L152. Should we be reading the name property from the constructor function, instead of creating an instance and looking for a name on that? Alternatively the name could be read as instance.constructor.name
. Here is what looks like the equivalent line but in Chai: https://github.com/chaijs/chai/blob/ab999d89171634e3b953765c6d0c8a7d454a4b59/lib/chai/core/assertions.js#L1054
Also, the error message format is slightly difference compared to standard Chai. Is this intentional, out of curiosity?
I'm trying to use mongoose promises and Q promises with chai-as-promised, but I keep on getting:
TypeError: Cannot call method 'equal' of undefined
Code:
var chai = require("chai")
, chaiAsPromised = require("chai-as-promised");
chai.use(chaiAsPromised);
...
describe('#getProject', function() {
it ('should get Project', function(done) {
return Project.findOne({_id:"000000000000000000000000"}).exec().should.eventually.equal("something");
});
});
I feel like I'm missing something obvious, but haven't been able to find it.
I just forked the repo in order to contribute some bugfixes, but the tests are failing for me right off the bat:
TypeError: Object #<Object> has no method 'indexOf'
at formatProperty (/Users/jason/Desktop/Dropbox/projects/chai-as-promised/node_modules/chai/lib/chai/utils/inspect.js:245:15)
at /Users/jason/Desktop/Dropbox/projects/chai-as-promised/node_modules/chai/lib/chai/utils/inspect.js:158:14
at Array.map (native)
at formatValue (/Users/jason/Desktop/Dropbox/projects/chai-as-promised/node_modules/chai/lib/chai/utils/inspect.js:157:19)
at Object.inspect (/Users/jason/Desktop/Dropbox/projects/chai-as-promised/node_modules/chai/lib/chai/utils/inspect.js:27:10)
at onTransformedFulfilled (/Users/jason/Desktop/Dropbox/projects/chai-as-promised/lib/chai-as-promised.js:176:66)
at _fulfilled (/Users/jason/Desktop/Dropbox/projects/chai-as-promised/node_modules/q/q.js:1020:54)
at resolvedValue.promiseDispatch.done (/Users/jason/Desktop/Dropbox/projects/chai-as-promised/node_modules/q/q.js:1050:30)
at makePromise.promise.promiseDispatch (/Users/jason/Desktop/Dropbox/projects/chai-as-promised/node_modules/q/q.js:642:13)
at Object._onImmediate (/Users/jason/Desktop/Dropbox/projects/chai-as-promised/node_modules/q/q.js:521:44)
at processImmediate [as _immediateCallback] (timers.js:330:15)
Somehow chai-as-promised is calling utils.inspect, and chai itself is choking on it. This is the code from chai-as-promised.js:173-177 that's part of the stack trace above:
if (Constructor) {
assertion.assert(constructorIsGood(),
"expected promise to be rejected with " + Constructor.prototype.name + " but it " +
"was rejected with " + utils.inspect(rejectionReason));
}
Maybe a version incompatibility? If the tests are working for you all, can someone do an npm ls
and paste the output? Here's what I've got for reference:
[email protected] /Users/jason/Desktop/Dropbox/projects/chai-as-promised
├── [email protected]
├── [email protected]
├─┬ [email protected]
│ ├─┬ [email protected]
│ │ └── [email protected]
│ ├── [email protected]
│ ├── [email protected]
│ └── [email protected]
├─┬ [email protected]
│ ├── [email protected]
│ ├── [email protected]
│ └─┬ [email protected]
│ └── [email protected]
├─┬ [email protected]
│ ├── [email protected]
│ ├── [email protected]
│ └─┬ [email protected]
│ ├── [email protected]
│ └── [email protected]
├─┬ [email protected]
│ ├── [email protected]
│ ├── [email protected]
│ ├─┬ [email protected]
│ │ ├── [email protected]
│ │ └── [email protected]
│ ├── [email protected]
│ └── [email protected]
├─┬ [email protected]
│ ├── [email protected]
│ ├── [email protected]
│ ├── [email protected]
│ ├── [email protected]
│ ├─┬ [email protected]
│ │ └── [email protected]
│ ├── [email protected]
│ └── [email protected]
├── [email protected]
├── [email protected]
└── [email protected]
I tried to test some of my mongoose models with mocha using the mongoose own promises (http://mongoosejs.com/docs/api.html#promise-js) with chai as promised.
If I try a simple
expect(myMongooseModel.findOne({}).exec()).to.eventually.exist.and.notify(done)
the mocha done() function is never called. I looked into it and it seems the fullfilment function (https://github.com/domenic/chai-as-promised/blob/master/lib/chai-as-promised.js#L244-L252) never gets called. Sorry I can not elaborate the error any deeper.
Q-lib promises work fine for me.
According to the source code mongoose promises correspond to the promises/a+ specification (https://github.com/LearnBoost/mongoose/blob/3.6.11/lib/promise.js#L171), so it should work.
expect(promise).to.be.rejected.with() seems to support only cases where the rejections reason is an object with a message
property. I assume this is so in order to support the use-case of rejecting with an Error object.
Why not support custom rejection reasons?
People keep trying to use Chai as Promised with them, but they are not Promises/A+ compliant and thus do not work. We should throw immediately when they show up, similarly to how we do for jQuery.
assert.throw accepts a string/regex to compare against the thrown error.message
eg:
assert.throw(function() {
throw new Error('error message');
}, 'this is not the error message', 'my msg');
fails with:
AssertionError: expected [Function] to throw error including 'this is not the error message' but got 'error message'
but:
var promise = new Promise(function(resolve, reject) {
reject(new Error('error message'));
});
return assert.isRejected(promise, 'this is not the error message', "optional msg");
does not fail
We're seeing this a lot using Chai as Promised at work. I think this is Chai as Promised's fault, somehow.
Chime in if you see it too.
Hello
In the code below i'm testing promise result. As it can be seen from the example . The function named myFunction
should reject promise for parameters 'a' and 's'. But when I run test I see the test passed in spite of that promise expected to be rejected. What was wrong in the code below ?
Thanks in advance
var chai = require('chai');
var sinon = require('sinon');
var util = require('util');
var Q = require('q');
var chaiAsPromised = require('chai-as-promised');
var assert = chai.assert;
chai.use(chaiAsPromised);
var myFunction = function(src,dest){
var d = Q.defer();
if (dest.indexOf('goodFile')>=0) {
console.log('Good name!!!');
d.resolve();
}
else {
console.log('Bad name!!!');
d.reject('Bad file name');
}
return d.promise;
};
describe('my tests',function(){
it('test promise',function(done){
var testPromise = myFunction('a','s');
testPromise.finally(function(){
assert.isFulfilled(testPromise, "optional message");
done();
});
});
});
Something seems to get lost when trying to compare two arrays using promise oriented expects (seems to behave the same with shoulds as well).
E.g. if I do:
expect(Q(['foo'])).to.eventually.equal(['bar']);
I'd expect to get a diff showing that one array has "foo" and then other "bar", but instead I get:
[
"bar"
]{}
NB: because I'll lose the coloring in GitHub the [ "bar" ]
is the expected and the {}
is the actual.
The equivalent immediate test:
expect(['foo']).to.equal(['bar']);
displays the right diff.
Here's a full test case that demonstrates the problem:
describe('fail', function() {
var chai = require("chai");
chai.use(require("chai-as-promised"));
var expect = chai.expect;
var Q = require('q');
require("mocha-as-promised")();
it('should display diff', function() {
return expect(Q(['foo'])).to.eventually.equal(['bar']);
});
it('does display a diff', function() {
expect(['foo']).to.equal(['bar']);
});
});
I'm having trouble using this library on promises that are resolved asynchronously.
I assumed I could write something like this:
(where getPendingPromise()
is a function that returns a promise that will resolve in a few milliseconds)
it('eventually fails with error', function(done) {
var promise = getPendingPromise();
promise.should.be.rejected.with('Some Error').and.notify(done);
});
In the code above, my promise is being resolved in the background, and I assumed this library would wait for resolution before making its assertion.
But what actually happens is it times out and done
is never called.
If I change the code to add a timeout, then the test passes:
it('eventually fails with error', function(done) {
var promise = getPendingPromise();
setTimeout(function() {
promise.should.be.rejected.with('Some Error').and.notify(done);
}, 1000);
});
So I wonder if this library can only work with resolved promises? All the internal tests seem to be articulated with already-resolved promises (the fulfilledPromise()
and rejectedPromise()
factories generate them).
Any clarification would be appreciated.
Right now I'm trying to assert that a method handles a promise while swallowing any errors which might otherwise be raised when the method terminates the chain with done()
. However, I'm unable to get the assertion in at the right time.
methodUnderTest = (promise) ->
# This method is written in such a way that I'd like it to fail the test below
promise.then(-> doSomething()).done()
it "does not raise an error on failure", (done) ->
Q.onerror = (err) -> throw err
sinon.spy(Q, "onerror")
promise = Q.reject(false)
methodUnderTest(promise)
promise.should.be.rejected.then((->
# I expect the following to fail, but it doesn't because it's run before Q.onerror gets called
Q.onerror.should.not.have.been.called
)).should.notify(done)
Is there a way to achieve this without using setTimeout
or similar? I'm using Mocha via the Konacha test harness.
It would be useful if assertion could test the value of the progress callback as defined by CommonJS Promises/A.
E.g.
promise.should.updateProgress;
promise.should.updateProgress.eql("progress message");
assert.updatesProgress(promise);
assert.updatesProgress(promise, /progress message/);
Using when.js, a test would look like this:
var dfd = when.defer();
dfd.progress("progress message");
dfd.reject(new Error("Fail!"));
assert.updatesProgress(dfd.promise, /message/);
Older versions of npm (I think I had 1.1.69 or so) silently ignore peerDependencies, so chai is not installed.
Perhaps there is some way to require an up-to-date npm?
I have [email protected] and [email protected] installed via npm.
I'm using chai-as-promised under mocha in protractor with the following preamble:
var chai = require('chai');
global.expect = chai.expect;
global.should = chai.should();
chai.use(require('chai-as-promised'));
The following type of asserts pass:
should.not.exist(null)
expect("foo").to.be.eql("foo")
"bar".should.be.eql("bar")
var title = browser.getTitle()
expect(title).to.eventually.be.eql(CONFIG.Title)
But the following assertion fails:
title.should.eventually.equal(CONFIG.Title)
With the following error:
TypeError: Cannot read property 'eventually' of undefined
This is very strange, as Object.prototype.should exists and object.should... assert style works - but not with promises.
the title promise looks like this:
{
then: [Function: then],
cancel: [Function: cancel],
isPending: [Function: isPending]
}
I'm making a http request that returns a q promise, then I call for the chai-as-promised (should) assert but when I evaluate the expression it is the promise it self.
I made a branch of the project with the tests, I', using vows: https://github.com/lucasfeliciano/restling/tree/test-parallel/
To test just run node spec/specs.js
.
Line 40 and 43 it is the tests that is passing but it shouldnt.
Using Mocha, this test:
var deferred = q.defer();
expect(deferred.promise).to.eventually
.equal('hello')
.and.notify(done);
deferred.resolve('goodbye');
Will fail as expected, but the failure message is:
actual expected
{} "hello"
(well kinda - I doctored the output so it would make sense without color support)
My unit test is passing even though the promise gets rejected.
return Q.all([ promise.should.eventually.be.an('Array'), promise.should.eventually.have.property('length', 4) ]);
In my logs I am getting the following error:
Unhandled rejection reason: expected [ Array(3) ] to have a property 'length' of 4, but got 3
Mocha and Chai as Promised seems to work for other tests, but what am I potentially doing wrong here?
I came acros this error message when writing test for jQuery defers. When I bypassed the sniffing of 'chai-as-promised' by def.pipe = null
the test failed as expected and passed as expected. So the matcher tested exactly the behavior I was looking for. I could not find any comments why it is incompatible with jQuery defers.
Why is this check here and why are jquery defers not supported?
You currently can't use chai-as-promised with jQuery's Deferred Promises. Specifically, the rejected assertions don't returned a fulfilled promise and the following will fail on the second assert:
var assertPromise = assert.isRejected(jQuery.Deferred().reject(new Error("fail!")));
assert.isFulfilled(assertPromise, "isRejected returns fulfilled promise");
The reason for this is that unlike the CommonJS Promises/A specification, jQuery's then()
method returns the original promise rather than a new promise.
jQuery has a pipe() method which is similar to the Promises/A's then()
. Changing the rejectedAsserter
to use the following makes it work correctly for jQuery.
var transformedPromise = Object.create(this.obj.pipe(onOriginalFulfilled, onOriginalRejected));
It would be great if chai-as-promised were aware of jQuery's behavior or if the creation of the transformedPromise
was pluggable s.t. jQuery tests could implement it using pipe()
.
Hi, I was writing a test where I'm expecting a string to be returned from a rejected promise.
For example, we have an expected result like:
before(function () {
var data = 'some error message different';
sinon.stub(myModule, 'myMethod').returns(new RSVP.Promise(function (resolve, reject) {
reject(data);
}));
result = myService.go(input);
});
it('Should return an error message', function (done) {
expect(result).to.eventually.be.rejectedWith('some error message').notify(done);
});
My assertion is passing since the rejectWith
method is using indexOf()
for strings and not a value comparison. Was this intentional or is this a bug?
The examples for expect
refer to a method named promiseFor
, does this exist?
If so where?
I would love to fix the examples but i can't for the life of me get it to work.
Cheers
I'm using Mocha 1.6.0, Chai 1.3.0, and Chai-as-promised 3.2.3. Testing fails with TypeError: Object prototype may only be an Object or null
even when I use a generic promise.
it('handles promises correctly', function(done) {
expect({
then: function (callback) {
setTimeout(1000, callback);
}
}).to.eventually.be.fulfilled.and.notify(done);
});
Is this the correct way to create promises, or is this a problem with Chai-as-promised?
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.