chai-as-promised 5.3.0 → 6.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE.txt CHANGED
@@ -1,4 +1,4 @@
1
- Copyright © 2012–2015 Domenic Denicola <d@domenic.me>
1
+ Copyright © 2012–2016 Domenic Denicola <d@domenic.me>
2
2
 
3
3
  This work is free. You can redistribute it and/or modify it under the
4
4
  terms of the Do What The Fuck You Want To Public License, Version 2,
package/README.md CHANGED
@@ -124,7 +124,7 @@ chaiAsPromised.transformAsserterArgs = function (args) {
124
124
  }
125
125
 
126
126
  Promise.resolve(2).should.eventually.equal(2); // will now fail!
127
- Promise.resolve(2).should.eventually.equal(3); // will now pass!
127
+ Promise.resolve(3).should.eventually.equal(2); // will now pass!
128
128
  ```
129
129
 
130
130
  The transform can even be asynchronous, returning a promise for an array instead of an array directly. An example of that might be using `Promise.all` so that an array of promises becomes a promise for an array. If you do that, then you can compare promises against other promises using the asserters:
@@ -144,7 +144,11 @@ Promise.resolve(2).should.eventually.be.within(Promise.resolve(1), Promise.resol
144
144
 
145
145
  ### Compatibility
146
146
 
147
- Chai as Promised is compatible with all promises following the [Promises/A+ specification][spec]. Notably, jQuery's promises were not up to spec before jQuery 3.0, and Chai as Promised will not work with them. In particular, Chai as Promised makes extensive use of the standard [transformation behavior][] of `then`, which jQuery<3.0 does not support.
147
+ Chai as Promised is compatible with all promises following the [Promises/A+ specification][spec].
148
+
149
+ Notably, jQuery's promises were not up to spec before jQuery 3.0, and Chai as Promised will not work with them. In particular, Chai as Promised makes extensive use of the standard [transformation behavior][] of `then`, which jQuery<3.0 does not support.
150
+
151
+ Angular promises have a special digest cycle for their processing, and [need extra setup code to work with Chai as Promised](http://stackoverflow.com/a/37374041/3191).
148
152
 
149
153
  ### Working with Non-Promise–Friendly Test Runners
150
154
 
@@ -202,31 +206,21 @@ var chai = require("chai");
202
206
  var chaiAsPromised = require("chai-as-promised");
203
207
 
204
208
  chai.use(chaiAsPromised);
205
- ```
206
-
207
- You can of course put this code in a common test fixture file; for an example using [Mocha][], see [the Chai as Promised tests themselves][fixturedemo].
208
-
209
- ### AMD
210
209
 
211
- Chai as Promised supports being used as an [AMD][amd] module, registering itself anonymously (just like Chai). So, assuming you have configured your loader to map the Chai and Chai as Promised files to the respective module IDs `"chai"` and `"chai-as-promised"`, you can use them as follows:
212
-
213
- ```javascript
214
- define(function (require, exports, module) {
215
- var chai = require("chai");
216
- var chaiAsPromised = require("chai-as-promised");
217
-
218
- chai.use(chaiAsPromised);
219
- });
210
+ // Then either:
211
+ var expect = chai.expect;
212
+ // or:
213
+ var assert = chai.assert;
214
+ // or:
215
+ chai.should();
216
+ // according to your preference of assertion style
220
217
  ```
221
218
 
222
- ### `<script>` tag
219
+ You can of course put this code in a common test fixture file; for an example using [Mocha][], see [the Chai as Promised tests themselves][fixturedemo].
223
220
 
224
- If you include Chai as Promised directly with a `<script>` tag, after the one for Chai itself, then it will automatically plug in to Chai and be ready for use:
221
+ ### In the Browser
225
222
 
226
- ```html
227
- <script src="chai.js"></script>
228
- <script src="chai-as-promised.js"></script>
229
- ```
223
+ To use Chai as Promised in environments that don't support Node.js-like CommonJS modules, you'll need to use a bundling tool like [browserify][].
230
224
 
231
225
  ### Karma
232
226
 
@@ -250,3 +244,4 @@ Chai as Promised is only compatible with modern browsers (IE ≥9, Safari ≥6,
250
244
  [sinon-chai]: https://github.com/domenic/sinon-chai
251
245
  [Karma]: https://karma-runner.github.io/
252
246
  [karma-chai-as-promised]: https://github.com/vlkosinov/karma-chai-as-promised
247
+ [browserify]: http://browserify.org/
@@ -1,375 +1,374 @@
1
- (function () {
2
- "use strict";
3
-
4
- // Module systems magic dance.
5
-
6
- /* istanbul ignore else */
7
- if (typeof require === "function" && typeof exports === "object" && typeof module === "object") {
8
- // NodeJS
9
- module.exports = chaiAsPromised;
10
- } else if (typeof define === "function" && define.amd) {
11
- // AMD
12
- define(function () {
13
- return chaiAsPromised;
14
- });
15
- } else {
16
- /*global self: false */
1
+ "use strict";
2
+ var checkError = require("check-error");
3
+
4
+ module.exports = function (chai, utils) {
5
+ var Assertion = chai.Assertion;
6
+ var assert = chai.assert;
7
+
8
+ // If we are using a version of Chai that has checkError on it,
9
+ // we want to use that version to be consistent. Otherwise, we use
10
+ // what was passed to the factory.
11
+ if (utils.checkError) {
12
+ checkError = utils.checkError;
13
+ }
17
14
 
18
- // Other environment (usually <script> tag): plug in to global chai instance directly.
19
- chai.use(chaiAsPromised);
15
+ function isLegacyJQueryPromise(thenable) {
16
+ // jQuery promises are Promises/A+-compatible since 3.0.0. jQuery 3.0.0 is also the first version
17
+ // to define the catch method.
18
+ return typeof thenable.catch !== "function" &&
19
+ typeof thenable.always === "function" &&
20
+ typeof thenable.done === "function" &&
21
+ typeof thenable.fail === "function" &&
22
+ typeof thenable.pipe === "function" &&
23
+ typeof thenable.progress === "function" &&
24
+ typeof thenable.state === "function";
25
+ }
20
26
 
21
- // Expose as a property of the global object so that consumers can configure the `transferPromiseness` property.
22
- self.chaiAsPromised = chaiAsPromised;
27
+ function assertIsAboutPromise(assertion) {
28
+ if (typeof assertion._obj.then !== "function") {
29
+ throw new TypeError(utils.inspect(assertion._obj) + " is not a thenable.");
30
+ }
31
+ if (isLegacyJQueryPromise(assertion._obj)) {
32
+ throw new TypeError("Chai as Promised is incompatible with thenables of jQuery<3.0.0, sorry! Please " +
33
+ "upgrade jQuery or use another Promises/A+ compatible library (see " +
34
+ "http://promisesaplus.com/).");
35
+ }
23
36
  }
24
37
 
25
- chaiAsPromised.transferPromiseness = function (assertion, promise) {
26
- assertion.then = promise.then.bind(promise);
27
- };
38
+ function method(name, asserter) {
39
+ utils.addMethod(Assertion.prototype, name, function () {
40
+ assertIsAboutPromise(this);
41
+ return asserter.apply(this, arguments);
42
+ });
43
+ }
28
44
 
29
- chaiAsPromised.transformAsserterArgs = function (values) {
30
- return values;
31
- };
45
+ function property(name, asserter) {
46
+ utils.addProperty(Assertion.prototype, name, function () {
47
+ assertIsAboutPromise(this);
48
+ return asserter.apply(this, arguments);
49
+ });
50
+ }
32
51
 
33
- function chaiAsPromised(chai, utils) {
34
- var Assertion = chai.Assertion;
35
- var assert = chai.assert;
36
-
37
- function isLegacyJQueryPromise(thenable) {
38
- // jQuery promises are Promises/A+-compatible since 3.0.0. jQuery 3.0.0 is also the first version
39
- // to define the catch method.
40
- return typeof thenable.catch !== "function" &&
41
- typeof thenable.always === "function" &&
42
- typeof thenable.done === "function" &&
43
- typeof thenable.fail === "function" &&
44
- typeof thenable.pipe === "function" &&
45
- typeof thenable.progress === "function" &&
46
- typeof thenable.state === "function";
47
- }
52
+ function doNotify(promise, done) {
53
+ promise.then(function () { done(); }, done);
54
+ }
48
55
 
49
- function assertIsAboutPromise(assertion) {
50
- if (typeof assertion._obj.then !== "function") {
51
- throw new TypeError(utils.inspect(assertion._obj) + " is not a thenable.");
52
- }
53
- if (isLegacyJQueryPromise(assertion._obj)) {
54
- throw new TypeError("Chai as Promised is incompatible with thenables of jQuery<3.0.0, sorry! Please " +
55
- "upgrade jQuery or use another Promises/A+ compatible library (see " +
56
- "http://promisesaplus.com/).");
57
- }
58
- }
56
+ // These are for clarity and to bypass Chai refusing to allow `undefined` as actual when used with `assert`.
57
+ function assertIfNegated(assertion, message, extra) {
58
+ assertion.assert(true, null, message, extra.expected, extra.actual);
59
+ }
59
60
 
60
- function method(name, asserter) {
61
- utils.addMethod(Assertion.prototype, name, function () {
62
- assertIsAboutPromise(this);
63
- return asserter.apply(this, arguments);
64
- });
65
- }
61
+ function assertIfNotNegated(assertion, message, extra) {
62
+ assertion.assert(false, message, null, extra.expected, extra.actual);
63
+ }
66
64
 
67
- function property(name, asserter) {
68
- utils.addProperty(Assertion.prototype, name, function () {
69
- assertIsAboutPromise(this);
70
- return asserter.apply(this, arguments);
71
- });
72
- }
65
+ function getBasePromise(assertion) {
66
+ // We need to chain subsequent asserters on top of ones in the chain already (consider
67
+ // `eventually.have.property("foo").that.equals("bar")`), only running them after the existing ones pass.
68
+ // So the first base-promise is `assertion._obj`, but after that we use the assertions themselves, i.e.
69
+ // previously derived promises, to chain off of.
70
+ return typeof assertion.then === "function" ? assertion : assertion._obj;
71
+ }
73
72
 
74
- function doNotify(promise, done) {
75
- promise.then(function () { done(); }, done);
76
- }
73
+ function getReasonName(reason) {
74
+ return (reason instanceof Error) ? reason.toString() : checkError.getConstructorName(reason);
75
+ }
77
76
 
78
- // These are for clarity and to bypass Chai refusing to allow `undefined` as actual when used with `assert`.
79
- function assertIfNegated(assertion, message, extra) {
80
- assertion.assert(true, null, message, extra.expected, extra.actual);
77
+ // Grab these first, before we modify `Assertion.prototype`.
78
+
79
+ var propertyNames = Object.getOwnPropertyNames(Assertion.prototype);
80
+
81
+ var propertyDescs = {};
82
+ propertyNames.forEach(function (name) {
83
+ propertyDescs[name] = Object.getOwnPropertyDescriptor(Assertion.prototype, name);
84
+ });
85
+
86
+ property("fulfilled", function () {
87
+ var that = this;
88
+ var derivedPromise = getBasePromise(that).then(
89
+ function (value) {
90
+ assertIfNegated(that,
91
+ "expected promise not to be fulfilled but it was fulfilled with #{act}",
92
+ { actual: value });
93
+ return value;
94
+ },
95
+ function (reason) {
96
+ assertIfNotNegated(that,
97
+ "expected promise to be fulfilled but it was rejected with #{act}",
98
+ { actual: getReasonName(reason) });
99
+ return reason;
100
+ }
101
+ );
102
+
103
+ module.exports.transferPromiseness(that, derivedPromise);
104
+ });
105
+
106
+ property("rejected", function () {
107
+ var that = this;
108
+ var derivedPromise = getBasePromise(that).then(
109
+ function (value) {
110
+ assertIfNotNegated(that,
111
+ "expected promise to be rejected but it was fulfilled with #{act}",
112
+ { actual: value });
113
+ return value;
114
+ },
115
+ function (reason) {
116
+ assertIfNegated(that,
117
+ "expected promise not to be rejected but it was rejected with #{act}",
118
+ { actual: getReasonName(reason) });
119
+
120
+ // Return the reason, transforming this into a fulfillment, to allow further assertions, e.g.
121
+ // `promise.should.be.rejected.and.eventually.equal("reason")`.
122
+ return reason;
123
+ }
124
+ );
125
+
126
+ module.exports.transferPromiseness(that, derivedPromise);
127
+ });
128
+
129
+ method("rejectedWith", function (errorLike, errMsgMatcher, message) {
130
+ var errorLikeName = null;
131
+ var negate = utils.flag(this, "negate") || false;
132
+
133
+ // rejectedWith with that is called without arguments is
134
+ // the same as a plain ".rejected" use.
135
+ if (errorLike === undefined && errMsgMatcher === undefined &&
136
+ message === undefined) {
137
+ /* jshint expr: true */
138
+ this.rejected;
139
+ return;
81
140
  }
82
141
 
83
- function assertIfNotNegated(assertion, message, extra) {
84
- assertion.assert(false, message, null, extra.expected, extra.actual);
142
+ if (message !== undefined) {
143
+ utils.flag(this, "message", message);
85
144
  }
86
145
 
87
- function getBasePromise(assertion) {
88
- // We need to chain subsequent asserters on top of ones in the chain already (consider
89
- // `eventually.have.property("foo").that.equals("bar")`), only running them after the existing ones pass.
90
- // So the first base-promise is `assertion._obj`, but after that we use the assertions themselves, i.e.
91
- // previously derived promises, to chain off of.
92
- return typeof assertion.then === "function" ? assertion : assertion._obj;
146
+ if (errorLike instanceof RegExp || typeof errorLike === "string") {
147
+ errMsgMatcher = errorLike;
148
+ errorLike = null;
149
+ } else if (errorLike && errorLike instanceof Error) {
150
+ errorLikeName = errorLike.toString();
151
+ } else if (typeof errorLike === "function") {
152
+ errorLikeName = checkError.getConstructorName(errorLike);
153
+ } else {
154
+ errorLike = null;
93
155
  }
156
+ var everyArgIsDefined = Boolean(errorLike && errMsgMatcher);
94
157
 
95
- // Grab these first, before we modify `Assertion.prototype`.
96
-
97
- var propertyNames = Object.getOwnPropertyNames(Assertion.prototype);
98
-
99
- var propertyDescs = {};
100
- propertyNames.forEach(function (name) {
101
- propertyDescs[name] = Object.getOwnPropertyDescriptor(Assertion.prototype, name);
102
- });
158
+ var matcherRelation = "including";
159
+ if (errMsgMatcher instanceof RegExp) {
160
+ matcherRelation = "matching";
161
+ }
103
162
 
104
- property("fulfilled", function () {
105
- var that = this;
106
- var derivedPromise = getBasePromise(that).then(
107
- function (value) {
108
- that._obj = value;
109
- assertIfNegated(that,
110
- "expected promise not to be fulfilled but it was fulfilled with #{act}",
111
- { actual: value });
112
- return value;
113
- },
114
- function (reason) {
115
- assertIfNotNegated(that,
116
- "expected promise to be fulfilled but it was rejected with #{act}",
117
- { actual: reason });
163
+ var that = this;
164
+ var derivedPromise = getBasePromise(that).then(
165
+ function (value) {
166
+ var assertionMessage = null;
167
+ var expected = null;
168
+
169
+ if (errorLike) {
170
+ assertionMessage = "expected promise to be rejected with #{exp} but it was fulfilled with " +
171
+ "#{act}";
172
+ expected = errorLikeName;
173
+ } else if (errMsgMatcher) {
174
+ assertionMessage = "expected promise to be rejected with an error " + matcherRelation +
175
+ " #{exp} but it was fulfilled with #{act}";
176
+ expected = errMsgMatcher;
118
177
  }
119
- );
120
-
121
- chaiAsPromised.transferPromiseness(that, derivedPromise);
122
- });
123
178
 
124
- property("rejected", function () {
125
- var that = this;
126
- var derivedPromise = getBasePromise(that).then(
127
- function (value) {
128
- that._obj = value;
129
- assertIfNotNegated(that,
130
- "expected promise to be rejected but it was fulfilled with #{act}",
131
- { actual: value });
132
- return value;
133
- },
134
- function (reason) {
135
- assertIfNegated(that,
136
- "expected promise not to be rejected but it was rejected with #{act}",
137
- { actual: reason });
138
-
139
- // Return the reason, transforming this into a fulfillment, to allow further assertions, e.g.
140
- // `promise.should.be.rejected.and.eventually.equal("reason")`.
141
- return reason;
142
- }
143
- );
144
-
145
- chaiAsPromised.transferPromiseness(that, derivedPromise);
146
- });
147
-
148
- method("rejectedWith", function (Constructor, message) {
149
- var desiredReason = null;
150
- var constructorName = null;
151
-
152
- if (Constructor instanceof RegExp || typeof Constructor === "string") {
153
- message = Constructor;
154
- Constructor = null;
155
- } else if (Constructor && Constructor instanceof Error) {
156
- desiredReason = Constructor;
157
- Constructor = null;
158
- message = null;
159
- } else if (typeof Constructor === "function") {
160
- constructorName = (new Constructor()).name;
161
- } else {
162
- Constructor = null;
163
- }
164
-
165
- var that = this;
166
- var derivedPromise = getBasePromise(that).then(
167
- function (value) {
168
- var assertionMessage = null;
169
- var expected = null;
170
-
171
- if (Constructor) {
172
- assertionMessage = "expected promise to be rejected with #{exp} but it was fulfilled with " +
173
- "#{act}";
174
- expected = constructorName;
175
- } else if (message) {
176
- var verb = message instanceof RegExp ? "matching" : "including";
177
- assertionMessage = "expected promise to be rejected with an error " + verb + " #{exp} but it " +
178
- "was fulfilled with #{act}";
179
- expected = message;
180
- } else if (desiredReason) {
181
- assertionMessage = "expected promise to be rejected with #{exp} but it was fulfilled with " +
182
- "#{act}";
183
- expected = desiredReason;
179
+ assertIfNotNegated(that, assertionMessage, { expected: expected, actual: value });
180
+ return value;
181
+ },
182
+ function (reason) {
183
+ var errorLikeCompatible = errorLike && (errorLike instanceof Error ?
184
+ checkError.compatibleInstance(reason, errorLike) :
185
+ checkError.compatibleConstructor(reason, errorLike));
186
+
187
+ var errMsgMatcherCompatible = errMsgMatcher && checkError.compatibleMessage(reason, errMsgMatcher);
188
+
189
+ var reasonName = getReasonName(reason);
190
+
191
+ if (negate && everyArgIsDefined) {
192
+ if (errorLikeCompatible && errMsgMatcherCompatible) {
193
+ that.assert(true,
194
+ null,
195
+ "expected promise not to be rejected with #{exp} but it was rejected " +
196
+ "with #{act}",
197
+ errorLikeName,
198
+ reasonName);
184
199
  }
185
-
186
- that._obj = value;
187
-
188
- assertIfNotNegated(that, assertionMessage, { expected: expected, actual: value });
189
- },
190
- function (reason) {
191
- if (Constructor) {
192
- that.assert(reason instanceof Constructor,
200
+ }
201
+ else {
202
+ if (errorLike) {
203
+ that.assert(errorLikeCompatible,
193
204
  "expected promise to be rejected with #{exp} but it was rejected with #{act}",
194
- "expected promise not to be rejected with #{exp} but it was rejected with #{act}",
195
- constructorName,
196
- reason);
205
+ "expected promise not to be rejected with #{exp} but it was rejected " +
206
+ "with #{act}",
207
+ errorLikeName,
208
+ reasonName);
197
209
  }
198
210
 
199
- var reasonMessage = utils.type(reason) === "object" && "message" in reason ?
200
- reason.message :
201
- "" + reason;
202
- if (message && reasonMessage !== null && reasonMessage !== undefined) {
203
- if (message instanceof RegExp) {
204
- that.assert(message.test(reasonMessage),
205
- "expected promise to be rejected with an error matching #{exp} but got #{act}",
206
- "expected promise not to be rejected with an error matching #{exp}",
207
- message,
208
- reasonMessage);
209
- }
210
- if (typeof message === "string") {
211
- that.assert(reasonMessage.indexOf(message) !== -1,
212
- "expected promise to be rejected with an error including #{exp} but got #{act}",
213
- "expected promise not to be rejected with an error including #{exp}",
214
- message,
215
- reasonMessage);
216
- }
217
- }
218
-
219
- if (desiredReason) {
220
- that.assert(reason === desiredReason,
221
- "expected promise to be rejected with #{exp} but it was rejected with #{act}",
222
- "expected promise not to be rejected with #{exp}",
223
- desiredReason,
224
- reason);
211
+ if (errMsgMatcher) {
212
+ that.assert(errMsgMatcherCompatible,
213
+ "expected promise to be rejected with an error " + matcherRelation +
214
+ " #{exp} but got #{act}",
215
+ "expected promise not to be rejected with an error " + matcherRelation +
216
+ " #{exp}",
217
+ errMsgMatcher,
218
+ checkError.getMessage(reason));
225
219
  }
226
220
  }
227
- );
228
221
 
229
- chaiAsPromised.transferPromiseness(that, derivedPromise);
230
- });
222
+ return reason;
223
+ }
224
+ );
231
225
 
232
- property("eventually", function () {
233
- utils.flag(this, "eventually", true);
234
- });
226
+ module.exports.transferPromiseness(that, derivedPromise);
227
+ });
235
228
 
236
- method("notify", function (done) {
237
- doNotify(getBasePromise(this), done);
238
- });
229
+ property("eventually", function () {
230
+ utils.flag(this, "eventually", true);
231
+ });
239
232
 
240
- method("become", function (value, message) {
241
- return this.eventually.deep.equal(value, message);
242
- });
233
+ method("notify", function (done) {
234
+ doNotify(getBasePromise(this), done);
235
+ });
243
236
 
244
- ////////
245
- // `eventually`
237
+ method("become", function (value, message) {
238
+ return this.eventually.deep.equal(value, message);
239
+ });
246
240
 
247
- // We need to be careful not to trigger any getters, thus `Object.getOwnPropertyDescriptor` usage.
248
- var methodNames = propertyNames.filter(function (name) {
249
- return name !== "assert" && typeof propertyDescs[name].value === "function";
250
- });
241
+ ////////
242
+ // `eventually`
251
243
 
252
- methodNames.forEach(function (methodName) {
253
- Assertion.overwriteMethod(methodName, function (originalMethod) {
254
- return function () {
255
- doAsserterAsyncAndAddThen(originalMethod, this, arguments);
256
- };
257
- });
258
- });
244
+ // We need to be careful not to trigger any getters, thus `Object.getOwnPropertyDescriptor` usage.
245
+ var methodNames = propertyNames.filter(function (name) {
246
+ return name !== "assert" && typeof propertyDescs[name].value === "function";
247
+ });
259
248
 
260
- var getterNames = propertyNames.filter(function (name) {
261
- return name !== "_obj" && typeof propertyDescs[name].get === "function";
249
+ methodNames.forEach(function (methodName) {
250
+ Assertion.overwriteMethod(methodName, function (originalMethod) {
251
+ return function () {
252
+ doAsserterAsyncAndAddThen(originalMethod, this, arguments);
253
+ };
262
254
  });
263
-
264
- getterNames.forEach(function (getterName) {
265
- // Chainable methods are things like `an`, which can work both for `.should.be.an.instanceOf` and as
266
- // `should.be.an("object")`. We need to handle those specially.
267
- var isChainableMethod = Assertion.prototype.__methods.hasOwnProperty(getterName);
268
-
269
- if (isChainableMethod) {
270
- Assertion.overwriteChainableMethod(
271
- getterName,
272
- function (originalMethod) {
273
- return function() {
274
- doAsserterAsyncAndAddThen(originalMethod, this, arguments);
275
- };
276
- },
277
- function (originalGetter) {
278
- return function() {
279
- doAsserterAsyncAndAddThen(originalGetter, this);
280
- };
281
- }
282
- );
283
- } else {
284
- Assertion.overwriteProperty(getterName, function (originalGetter) {
285
- return function () {
255
+ });
256
+
257
+ var getterNames = propertyNames.filter(function (name) {
258
+ return name !== "_obj" && typeof propertyDescs[name].get === "function";
259
+ });
260
+
261
+ getterNames.forEach(function (getterName) {
262
+ // Chainable methods are things like `an`, which can work both for `.should.be.an.instanceOf` and as
263
+ // `should.be.an("object")`. We need to handle those specially.
264
+ var isChainableMethod = Assertion.prototype.__methods.hasOwnProperty(getterName);
265
+
266
+ if (isChainableMethod) {
267
+ Assertion.overwriteChainableMethod(
268
+ getterName,
269
+ function (originalMethod) {
270
+ return function() {
271
+ doAsserterAsyncAndAddThen(originalMethod, this, arguments);
272
+ };
273
+ },
274
+ function (originalGetter) {
275
+ return function() {
286
276
  doAsserterAsyncAndAddThen(originalGetter, this);
287
277
  };
288
- });
289
- }
290
- });
291
-
292
- function doAsserterAsyncAndAddThen(asserter, assertion, args) {
293
- // Since we're intercepting all methods/properties, we need to just pass through if they don't want
294
- // `eventually`, or if we've already fulfilled the promise (see below).
295
- if (!utils.flag(assertion, "eventually")) {
296
- return asserter.apply(assertion, args);
297
- }
298
-
299
- var derivedPromise = getBasePromise(assertion).then(function (value) {
300
- // Set up the environment for the asserter to actually run: `_obj` should be the fulfillment value, and
301
- // now that we have the value, we're no longer in "eventually" mode, so we won't run any of this code,
302
- // just the base Chai code that we get to via the short-circuit above.
303
- assertion._obj = value;
304
- utils.flag(assertion, "eventually", false);
305
-
306
- return args ? chaiAsPromised.transformAsserterArgs(args) : args;
307
- }).then(function (args) {
308
- asserter.apply(assertion, args);
309
-
310
- // Because asserters, for example `property`, can change the value of `_obj` (i.e. change the "object"
311
- // flag), we need to communicate this value change to subsequent chained asserters. Since we build a
312
- // promise chain paralleling the asserter chain, we can use it to communicate such changes.
313
- return assertion._obj;
278
+ }
279
+ );
280
+ } else {
281
+ Assertion.overwriteProperty(getterName, function (originalGetter) {
282
+ return function () {
283
+ doAsserterAsyncAndAddThen(originalGetter, this);
284
+ };
314
285
  });
286
+ }
287
+ });
315
288
 
316
- chaiAsPromised.transferPromiseness(assertion, derivedPromise);
289
+ function doAsserterAsyncAndAddThen(asserter, assertion, args) {
290
+ // Since we're intercepting all methods/properties, we need to just pass through if they don't want
291
+ // `eventually`, or if we've already fulfilled the promise (see below).
292
+ if (!utils.flag(assertion, "eventually")) {
293
+ return asserter.apply(assertion, args);
317
294
  }
318
295
 
319
- ///////
320
- // Now use the `Assertion` framework to build an `assert` interface.
321
- var originalAssertMethods = Object.getOwnPropertyNames(assert).filter(function (propName) {
322
- return typeof assert[propName] === "function";
296
+ var derivedPromise = getBasePromise(assertion).then(function (value) {
297
+ // Set up the environment for the asserter to actually run: `_obj` should be the fulfillment value, and
298
+ // now that we have the value, we're no longer in "eventually" mode, so we won't run any of this code,
299
+ // just the base Chai code that we get to via the short-circuit above.
300
+ assertion._obj = value;
301
+ utils.flag(assertion, "eventually", false);
302
+
303
+ return args ? module.exports.transformAsserterArgs(args) : args;
304
+ }).then(function (args) {
305
+ asserter.apply(assertion, args);
306
+
307
+ // Because asserters, for example `property`, can change the value of `_obj` (i.e. change the "object"
308
+ // flag), we need to communicate this value change to subsequent chained asserters. Since we build a
309
+ // promise chain paralleling the asserter chain, we can use it to communicate such changes.
310
+ return assertion._obj;
323
311
  });
324
312
 
325
- assert.isFulfilled = function (promise, message) {
326
- return (new Assertion(promise, message)).to.be.fulfilled;
327
- };
328
-
329
- assert.isRejected = function (promise, toTestAgainst, message) {
330
- if (typeof toTestAgainst === "string") {
331
- message = toTestAgainst;
332
- toTestAgainst = undefined;
333
- }
313
+ module.exports.transferPromiseness(assertion, derivedPromise);
314
+ }
334
315
 
335
- var assertion = (new Assertion(promise, message));
336
- return toTestAgainst !== undefined ? assertion.to.be.rejectedWith(toTestAgainst) : assertion.to.be.rejected;
337
- };
316
+ ///////
317
+ // Now use the `Assertion` framework to build an `assert` interface.
318
+ var originalAssertMethods = Object.getOwnPropertyNames(assert).filter(function (propName) {
319
+ return typeof assert[propName] === "function";
320
+ });
338
321
 
339
- assert.becomes = function (promise, value, message) {
340
- return assert.eventually.deepEqual(promise, value, message);
341
- };
322
+ assert.isFulfilled = function (promise, message) {
323
+ return (new Assertion(promise, message)).to.be.fulfilled;
324
+ };
342
325
 
343
- assert.doesNotBecome = function (promise, value, message) {
344
- return assert.eventually.notDeepEqual(promise, value, message);
345
- };
326
+ assert.isRejected = function (promise, errorLike, errMsgMatcher, message) {
327
+ var assertion = (new Assertion(promise, message));
328
+ return assertion.to.be.rejectedWith(errorLike, errMsgMatcher, message);
329
+ };
346
330
 
347
- assert.eventually = {};
348
- originalAssertMethods.forEach(function (assertMethodName) {
349
- assert.eventually[assertMethodName] = function (promise) {
350
- var otherArgs = Array.prototype.slice.call(arguments, 1);
331
+ assert.becomes = function (promise, value, message) {
332
+ return assert.eventually.deepEqual(promise, value, message);
333
+ };
351
334
 
352
- var customRejectionHandler;
353
- var message = arguments[assert[assertMethodName].length - 1];
354
- if (typeof message === "string") {
355
- customRejectionHandler = function (reason) {
356
- throw new chai.AssertionError(message + "\n\nOriginal reason: " + utils.inspect(reason));
357
- };
358
- }
335
+ assert.doesNotBecome = function (promise, value, message) {
336
+ return assert.eventually.notDeepEqual(promise, value, message);
337
+ };
359
338
 
360
- var returnedPromise = promise.then(
361
- function (fulfillmentValue) {
362
- return assert[assertMethodName].apply(assert, [fulfillmentValue].concat(otherArgs));
363
- },
364
- customRejectionHandler
365
- );
339
+ assert.eventually = {};
340
+ originalAssertMethods.forEach(function (assertMethodName) {
341
+ assert.eventually[assertMethodName] = function (promise) {
342
+ var otherArgs = Array.prototype.slice.call(arguments, 1);
366
343
 
367
- returnedPromise.notify = function (done) {
368
- doNotify(returnedPromise, done);
344
+ var customRejectionHandler;
345
+ var message = arguments[assert[assertMethodName].length - 1];
346
+ if (typeof message === "string") {
347
+ customRejectionHandler = function (reason) {
348
+ throw new chai.AssertionError(message + "\n\nOriginal reason: " + utils.inspect(reason));
369
349
  };
350
+ }
351
+
352
+ var returnedPromise = promise.then(
353
+ function (fulfillmentValue) {
354
+ return assert[assertMethodName].apply(assert, [fulfillmentValue].concat(otherArgs));
355
+ },
356
+ customRejectionHandler
357
+ );
370
358
 
371
- return returnedPromise;
359
+ returnedPromise.notify = function (done) {
360
+ doNotify(returnedPromise, done);
372
361
  };
373
- });
374
- }
375
- }());
362
+
363
+ return returnedPromise;
364
+ };
365
+ });
366
+ };
367
+
368
+ module.exports.transferPromiseness = function (assertion, promise) {
369
+ assertion.then = promise.then.bind(promise);
370
+ };
371
+
372
+ module.exports.transformAsserterArgs = function (values) {
373
+ return values;
374
+ };
package/package.json CHANGED
@@ -11,7 +11,7 @@
11
11
  "promises",
12
12
  "promises-aplus"
13
13
  ],
14
- "version": "5.3.0",
14
+ "version": "6.0.0",
15
15
  "author": "Domenic Denicola <d@domenic.me> (https://domenic.me)",
16
16
  "license": "WTFPL",
17
17
  "repository": "domenic/chai-as-promised",
@@ -23,21 +23,21 @@
23
23
  "test": "npm run test-plugin && npm run test-intercompatibility",
24
24
  "test-plugin": "mocha",
25
25
  "test-intercompatibility": "mocha test-intercompatibility --opts test-intercompatibility/mocha.opts",
26
- "test-browser-jquery": "coffee ./test/browser/runner.coffee jquery",
27
- "test-browser-q": "coffee ./test/browser/runner.coffee q",
28
- "test-browser-when": "coffee ./test/browser/runner.coffee when",
29
26
  "lint": "jshint ./lib",
30
27
  "cover": "istanbul cover node_modules/mocha/bin/_mocha && opener ./coverage/lcov-report/lib/chai-as-promised.js.html"
31
28
  },
29
+ "dependencies": {
30
+ "check-error": "^1.0.2"
31
+ },
32
32
  "peerDependencies": {
33
33
  "chai": ">= 2.1.2 < 4"
34
34
  },
35
35
  "devDependencies": {
36
36
  "chai": "^3.0.0",
37
37
  "coffee-script": "1.10.0",
38
- "istanbul": "0.4.1",
39
38
  "ecstatic": "^1.3.1",
40
39
  "glob": "^6.0.1",
40
+ "istanbul": "0.4.1",
41
41
  "jshint": "^2.8.0",
42
42
  "mocha": "^2.3.4",
43
43
  "opener": "^1.4.1",