chai-as-promised 7.1.2 → 8.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 ADDED
@@ -0,0 +1,23 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2012-2016 Domenic Denicola
4
+ Copyright (c) 2004 Sam Hocevar
5
+ Copyright (c) 2024 Chai Maintainers
6
+
7
+ Permission is hereby granted, free of charge, to any person obtaining a copy
8
+ of this software and associated documentation files (the "Software"), to deal
9
+ in the Software without restriction, including without limitation the rights
10
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11
+ copies of the Software, and to permit persons to whom the Software is
12
+ furnished to do so, subject to the following conditions:
13
+
14
+ The above copyright notice and this permission notice shall be included in all
15
+ copies or substantial portions of the Software.
16
+
17
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23
+ SOFTWARE.
package/README.md CHANGED
@@ -107,11 +107,13 @@ return promise.then(null, null, progressSpy).then(function () {
107
107
  By default, the promises returned by Chai as Promised's assertions are regular Chai assertion objects, extended with a single `then` method derived from the input promise. To change this behavior, for instance to output a promise with more useful sugar methods such as are found in most promise libraries, you can override `chaiAsPromised.transferPromiseness`. Here's an example that transfer's Q's `finally` and `done` methods:
108
108
 
109
109
  ```js
110
- chaiAsPromised.transferPromiseness = function (assertion, promise) {
110
+ import {setTransferPromiseness} from 'chai-as-promised';
111
+
112
+ setTransferPromiseness(function (assertion, promise) {
111
113
  assertion.then = promise.then.bind(promise); // this is all you get by default
112
114
  assertion.finally = promise.finally.bind(promise);
113
115
  assertion.done = promise.done.bind(promise);
114
- };
116
+ });
115
117
  ```
116
118
 
117
119
  ### Transforming Arguments to the Asserters
@@ -119,9 +121,11 @@ chaiAsPromised.transferPromiseness = function (assertion, promise) {
119
121
  Another advanced customization hook Chai as Promised allows is if you want to transform the arguments to the asserters, possibly asynchronously. Here is a toy example:
120
122
 
121
123
  ```js
122
- chaiAsPromised.transformAsserterArgs = function (args) {
124
+ import {transformAsserterArgs} from 'chai-as-promised';
125
+
126
+ setTransformAsserterArgs(function (args) {
123
127
  return args.map(function (x) { return x + 1; });
124
- }
128
+ });
125
129
 
126
130
  Promise.resolve(2).should.eventually.equal(2); // will now fail!
127
131
  Promise.resolve(3).should.eventually.equal(2); // will now pass!
@@ -133,9 +137,9 @@ The transform can even be asynchronous, returning a promise for an array instead
133
137
  // This will normally fail, since within() only works on numbers.
134
138
  Promise.resolve(2).should.eventually.be.within(Promise.resolve(1), Promise.resolve(6));
135
139
 
136
- chaiAsPromised.transformAsserterArgs = function (args) {
140
+ setTransformAsserterArgs(function (args) {
137
141
  return Promise.all(args);
138
- };
142
+ });
139
143
 
140
144
  // But now it will pass, since we transformed the array of promises for numbers into
141
145
  // (a promise for) an array of numbers
@@ -213,15 +217,15 @@ This will pass any failures of the individual promise assertions up to the test
213
217
  Do an `npm install chai-as-promised` to get up and running. Then:
214
218
 
215
219
  ```javascript
216
- var chai = require("chai");
217
- var chaiAsPromised = require("chai-as-promised");
220
+ import * as chai from 'chai';
221
+ import chaiAsPromised from 'chai-as-promised';
218
222
 
219
223
  chai.use(chaiAsPromised);
220
224
 
221
225
  // Then either:
222
- var expect = chai.expect;
226
+ const expect = chai.expect;
223
227
  // or:
224
- var assert = chai.assert;
228
+ const assert = chai.assert;
225
229
  // or:
226
230
  chai.should();
227
231
  // according to your preference of assertion style
@@ -231,14 +235,12 @@ You can of course put this code in a common test fixture file; for an example us
231
235
 
232
236
  **Note when using other Chai plugins:** Chai as Promised finds all currently-registered asserters and promisifies them, at the time it is installed. Thus, you should install Chai as Promised _last_, after any other Chai plugins, if you expect their asserters to be promisified.
233
237
 
234
- ### In the Browser
235
-
236
- 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](http://browserify.org/). See also the note below about browser compatibility.
237
-
238
238
  ### Karma
239
239
 
240
240
  If you're using [Karma](https://karma-runner.github.io/), check out the accompanying [karma-chai-as-promised](https://github.com/vlkosinov/karma-chai-as-promised) plugin.
241
241
 
242
242
  ### Browser/Node Compatibility
243
243
 
244
- Chai as Promised requires Node v4+ or a browser with equivalent support for modern JavaScript syntax. If your browser doesn't support modern JavaScript syntax, you'll need to transpile it down using a tool like [Babel](http://babeljs.io/).
244
+ Chai as Promised requires support for ES modules and modern JavaScript syntax.
245
+ If your browser doesn't support this, you will need to transpile it down using
246
+ a tool like [Babel](https://babeljs.io/).
@@ -1,361 +1,453 @@
1
- "use strict";
2
- /* eslint-disable no-invalid-this */
3
- let checkError = require("check-error");
4
-
5
- module.exports = (chai, utils) => {
6
- const Assertion = chai.Assertion;
7
- const assert = chai.assert;
8
- const proxify = utils.proxify;
9
-
10
- // If we are using a version of Chai that has checkError on it,
11
- // we want to use that version to be consistent. Otherwise, we use
12
- // what was passed to the factory.
13
- if (utils.checkError) {
14
- checkError = utils.checkError;
1
+ import * as checkErrorDefault from 'check-error';
2
+
3
+ let checkError = checkErrorDefault;
4
+
5
+ export default function (chai, utils) {
6
+ const Assertion = chai.Assertion;
7
+ const assert = chai.assert;
8
+ const proxify = utils.proxify;
9
+
10
+ // If we are using a version of Chai that has checkError on it,
11
+ // we want to use that version to be consistent. Otherwise, we use
12
+ // what was passed to the factory.
13
+ if (utils.checkError) {
14
+ checkError = utils.checkError;
15
+ }
16
+
17
+ function isLegacyJQueryPromise(thenable) {
18
+ // jQuery promises are Promises/A+-compatible since 3.0.0. jQuery 3.0.0 is also the first version
19
+ // to define the catch method.
20
+ return (
21
+ typeof thenable.catch !== 'function' &&
22
+ typeof thenable.always === 'function' &&
23
+ typeof thenable.done === 'function' &&
24
+ typeof thenable.fail === 'function' &&
25
+ typeof thenable.pipe === 'function' &&
26
+ typeof thenable.progress === 'function' &&
27
+ typeof thenable.state === 'function'
28
+ );
29
+ }
30
+
31
+ function assertIsAboutPromise(assertion) {
32
+ if (typeof assertion._obj.then !== 'function') {
33
+ throw new TypeError(
34
+ utils.inspect(assertion._obj) + ' is not a thenable.'
35
+ );
15
36
  }
16
-
17
- function isLegacyJQueryPromise(thenable) {
18
- // jQuery promises are Promises/A+-compatible since 3.0.0. jQuery 3.0.0 is also the first version
19
- // to define the catch method.
20
- return typeof thenable.catch !== "function" &&
21
- typeof thenable.always === "function" &&
22
- typeof thenable.done === "function" &&
23
- typeof thenable.fail === "function" &&
24
- typeof thenable.pipe === "function" &&
25
- typeof thenable.progress === "function" &&
26
- typeof thenable.state === "function";
27
- }
28
-
29
- function assertIsAboutPromise(assertion) {
30
- if (typeof assertion._obj.then !== "function") {
31
- throw new TypeError(utils.inspect(assertion._obj) + " is not a thenable.");
32
- }
33
- if (isLegacyJQueryPromise(assertion._obj)) {
34
- throw new TypeError("Chai as Promised is incompatible with thenables of jQuery<3.0.0, sorry! Please " +
35
- "upgrade jQuery or use another Promises/A+ compatible library (see " +
36
- "http://promisesaplus.com/).");
37
- }
37
+ if (isLegacyJQueryPromise(assertion._obj)) {
38
+ throw new TypeError(
39
+ 'Chai as Promised is incompatible with thenables of jQuery<3.0.0, sorry! Please ' +
40
+ 'upgrade jQuery or use another Promises/A+ compatible library (see ' +
41
+ 'http://promisesaplus.com/).'
42
+ );
38
43
  }
44
+ }
39
45
 
40
- function proxifyIfSupported(assertion) {
41
- return proxify === undefined ? assertion : proxify(assertion);
42
- }
43
-
44
- function method(name, asserter) {
45
- utils.addMethod(Assertion.prototype, name, function () {
46
- assertIsAboutPromise(this);
47
- return asserter.apply(this, arguments);
48
- });
49
- }
50
-
51
- function property(name, asserter) {
52
- utils.addProperty(Assertion.prototype, name, function () {
53
- assertIsAboutPromise(this);
54
- return proxifyIfSupported(asserter.apply(this, arguments));
55
- });
56
- }
46
+ function proxifyIfSupported(assertion) {
47
+ return proxify === undefined ? assertion : proxify(assertion);
48
+ }
57
49
 
58
- function doNotify(promise, done) {
59
- promise.then(() => done(), done);
60
- }
50
+ function method(name, asserter) {
51
+ utils.addMethod(Assertion.prototype, name, function () {
52
+ assertIsAboutPromise(this);
53
+ return asserter.apply(this, arguments);
54
+ });
55
+ }
61
56
 
62
- // These are for clarity and to bypass Chai refusing to allow `undefined` as actual when used with `assert`.
63
- function assertIfNegated(assertion, message, extra) {
64
- assertion.assert(true, null, message, extra.expected, extra.actual);
65
- }
57
+ function property(name, asserter) {
58
+ utils.addProperty(Assertion.prototype, name, function () {
59
+ assertIsAboutPromise(this);
60
+ return proxifyIfSupported(asserter.apply(this, arguments));
61
+ });
62
+ }
63
+
64
+ function doNotify(promise, done) {
65
+ promise.then(() => done(), done);
66
+ }
67
+
68
+ // These are for clarity and to bypass Chai refusing to allow `undefined` as actual when used with `assert`.
69
+ function assertIfNegated(assertion, message, extra) {
70
+ assertion.assert(true, null, message, extra.expected, extra.actual);
71
+ }
72
+
73
+ function assertIfNotNegated(assertion, message, extra) {
74
+ assertion.assert(false, message, null, extra.expected, extra.actual);
75
+ }
76
+
77
+ function getBasePromise(assertion) {
78
+ // We need to chain subsequent asserters on top of ones in the chain already (consider
79
+ // `eventually.have.property("foo").that.equals("bar")`), only running them after the existing ones pass.
80
+ // So the first base-promise is `assertion._obj`, but after that we use the assertions themselves, i.e.
81
+ // previously derived promises, to chain off of.
82
+ return typeof assertion.then === 'function' ? assertion : assertion._obj;
83
+ }
84
+
85
+ function getReasonName(reason) {
86
+ return reason instanceof Error
87
+ ? reason.toString()
88
+ : checkError.getConstructorName(reason);
89
+ }
90
+
91
+ // Grab these first, before we modify `Assertion.prototype`.
92
+
93
+ const propertyNames = Object.getOwnPropertyNames(Assertion.prototype);
94
+
95
+ const propertyDescs = {};
96
+ for (const name of propertyNames) {
97
+ propertyDescs[name] = Object.getOwnPropertyDescriptor(
98
+ Assertion.prototype,
99
+ name
100
+ );
101
+ }
102
+
103
+ property('fulfilled', function () {
104
+ const derivedPromise = getBasePromise(this).then(
105
+ (value) => {
106
+ assertIfNegated(
107
+ this,
108
+ 'expected promise not to be fulfilled but it was fulfilled with #{act}',
109
+ {actual: value}
110
+ );
111
+ return value;
112
+ },
113
+ (reason) => {
114
+ assertIfNotNegated(
115
+ this,
116
+ 'expected promise to be fulfilled but it was rejected with #{act}',
117
+ {actual: getReasonName(reason)}
118
+ );
119
+ return reason;
120
+ }
121
+ );
122
+
123
+ transferPromiseness(this, derivedPromise);
124
+ return this;
125
+ });
126
+
127
+ property('rejected', function () {
128
+ const derivedPromise = getBasePromise(this).then(
129
+ (value) => {
130
+ assertIfNotNegated(
131
+ this,
132
+ 'expected promise to be rejected but it was fulfilled with #{act}',
133
+ {actual: value}
134
+ );
135
+ return value;
136
+ },
137
+ (reason) => {
138
+ assertIfNegated(
139
+ this,
140
+ 'expected promise not to be rejected but it was rejected with #{act}',
141
+ {actual: getReasonName(reason)}
142
+ );
66
143
 
67
- function assertIfNotNegated(assertion, message, extra) {
68
- assertion.assert(false, message, null, extra.expected, extra.actual);
144
+ // Return the reason, transforming this into a fulfillment, to allow further assertions, e.g.
145
+ // `promise.should.be.rejected.and.eventually.equal("reason")`.
146
+ return reason;
147
+ }
148
+ );
149
+
150
+ transferPromiseness(this, derivedPromise);
151
+ return this;
152
+ });
153
+
154
+ method('rejectedWith', function (errorLike, errMsgMatcher, message) {
155
+ let errorLikeName = null;
156
+ const negate = utils.flag(this, 'negate') || false;
157
+
158
+ // rejectedWith with that is called without arguments is
159
+ // the same as a plain ".rejected" use.
160
+ if (
161
+ errorLike === undefined &&
162
+ errMsgMatcher === undefined &&
163
+ message === undefined
164
+ ) {
165
+ /* eslint-disable no-unused-expressions */
166
+ return this.rejected;
167
+ /* eslint-enable no-unused-expressions */
69
168
  }
70
169
 
71
- function getBasePromise(assertion) {
72
- // We need to chain subsequent asserters on top of ones in the chain already (consider
73
- // `eventually.have.property("foo").that.equals("bar")`), only running them after the existing ones pass.
74
- // So the first base-promise is `assertion._obj`, but after that we use the assertions themselves, i.e.
75
- // previously derived promises, to chain off of.
76
- return typeof assertion.then === "function" ? assertion : assertion._obj;
170
+ if (message !== undefined) {
171
+ utils.flag(this, 'message', message);
77
172
  }
78
173
 
79
- function getReasonName(reason) {
80
- return reason instanceof Error ? reason.toString() : checkError.getConstructorName(reason);
174
+ if (errorLike instanceof RegExp || typeof errorLike === 'string') {
175
+ errMsgMatcher = errorLike;
176
+ errorLike = null;
177
+ } else if (errorLike && errorLike instanceof Error) {
178
+ errorLikeName = errorLike.toString();
179
+ } else if (typeof errorLike === 'function') {
180
+ errorLikeName = checkError.getConstructorName(errorLike);
181
+ } else {
182
+ errorLike = null;
81
183
  }
184
+ const everyArgIsDefined = Boolean(errorLike && errMsgMatcher);
82
185
 
83
- // Grab these first, before we modify `Assertion.prototype`.
84
-
85
- const propertyNames = Object.getOwnPropertyNames(Assertion.prototype);
86
-
87
- const propertyDescs = {};
88
- for (const name of propertyNames) {
89
- propertyDescs[name] = Object.getOwnPropertyDescriptor(Assertion.prototype, name);
186
+ let matcherRelation = 'including';
187
+ if (errMsgMatcher instanceof RegExp) {
188
+ matcherRelation = 'matching';
90
189
  }
91
190
 
92
- property("fulfilled", function () {
93
- const derivedPromise = getBasePromise(this).then(
94
- value => {
95
- assertIfNegated(this,
96
- "expected promise not to be fulfilled but it was fulfilled with #{act}",
97
- { actual: value });
98
- return value;
99
- },
100
- reason => {
101
- assertIfNotNegated(this,
102
- "expected promise to be fulfilled but it was rejected with #{act}",
103
- { actual: getReasonName(reason) });
104
- return reason;
105
- }
106
- );
107
-
108
- module.exports.transferPromiseness(this, derivedPromise);
109
- return this;
110
- });
111
-
112
- property("rejected", function () {
113
- const derivedPromise = getBasePromise(this).then(
114
- value => {
115
- assertIfNotNegated(this,
116
- "expected promise to be rejected but it was fulfilled with #{act}",
117
- { actual: value });
118
- return value;
119
- },
120
- reason => {
121
- assertIfNegated(this,
122
- "expected promise not to be rejected but it was rejected with #{act}",
123
- { actual: getReasonName(reason) });
124
-
125
- // Return the reason, transforming this into a fulfillment, to allow further assertions, e.g.
126
- // `promise.should.be.rejected.and.eventually.equal("reason")`.
127
- return reason;
128
- }
129
- );
130
-
131
- module.exports.transferPromiseness(this, derivedPromise);
132
- return this;
133
- });
134
-
135
- method("rejectedWith", function (errorLike, errMsgMatcher, message) {
136
- let errorLikeName = null;
137
- const negate = utils.flag(this, "negate") || false;
138
-
139
- // rejectedWith with that is called without arguments is
140
- // the same as a plain ".rejected" use.
141
- if (errorLike === undefined && errMsgMatcher === undefined &&
142
- message === undefined) {
143
- /* eslint-disable no-unused-expressions */
144
- return this.rejected;
145
- /* eslint-enable no-unused-expressions */
191
+ const derivedPromise = getBasePromise(this).then(
192
+ (value) => {
193
+ let assertionMessage = null;
194
+ let expected = null;
195
+
196
+ if (errorLike) {
197
+ assertionMessage =
198
+ 'expected promise to be rejected with #{exp} but it was fulfilled with #{act}';
199
+ expected = errorLikeName;
200
+ } else if (errMsgMatcher) {
201
+ assertionMessage =
202
+ `expected promise to be rejected with an error ${matcherRelation} #{exp} but ` +
203
+ `it was fulfilled with #{act}`;
204
+ expected = errMsgMatcher;
146
205
  }
147
206
 
148
- if (message !== undefined) {
149
- utils.flag(this, "message", message);
150
- }
151
-
152
- if (errorLike instanceof RegExp || typeof errorLike === "string") {
153
- errMsgMatcher = errorLike;
154
- errorLike = null;
155
- } else if (errorLike && errorLike instanceof Error) {
156
- errorLikeName = errorLike.toString();
157
- } else if (typeof errorLike === "function") {
158
- errorLikeName = checkError.getConstructorName(errorLike);
207
+ assertIfNotNegated(this, assertionMessage, {expected, actual: value});
208
+ return value;
209
+ },
210
+ (reason) => {
211
+ const errorLikeCompatible =
212
+ errorLike &&
213
+ (errorLike instanceof Error
214
+ ? checkError.compatibleInstance(reason, errorLike)
215
+ : checkError.compatibleConstructor(reason, errorLike));
216
+
217
+ const errMsgMatcherCompatible =
218
+ errMsgMatcher === reason ||
219
+ (errMsgMatcher &&
220
+ reason &&
221
+ checkError.compatibleMessage(reason, errMsgMatcher));
222
+
223
+ const reasonName = getReasonName(reason);
224
+
225
+ if (negate && everyArgIsDefined) {
226
+ if (errorLikeCompatible && errMsgMatcherCompatible) {
227
+ this.assert(
228
+ true,
229
+ null,
230
+ 'expected promise not to be rejected with #{exp} but it was rejected ' +
231
+ 'with #{act}',
232
+ errorLikeName,
233
+ reasonName
234
+ );
235
+ }
159
236
  } else {
160
- errorLike = null;
237
+ if (errorLike) {
238
+ this.assert(
239
+ errorLikeCompatible,
240
+ 'expected promise to be rejected with #{exp} but it was rejected with #{act}',
241
+ 'expected promise not to be rejected with #{exp} but it was rejected ' +
242
+ 'with #{act}',
243
+ errorLikeName,
244
+ reasonName
245
+ );
246
+ }
247
+
248
+ if (errMsgMatcher) {
249
+ this.assert(
250
+ errMsgMatcherCompatible,
251
+ `expected promise to be rejected with an error ${matcherRelation} #{exp} but got ` +
252
+ `#{act}`,
253
+ `expected promise not to be rejected with an error ${matcherRelation} #{exp}`,
254
+ errMsgMatcher,
255
+ checkError.getMessage(reason)
256
+ );
257
+ }
161
258
  }
162
- const everyArgIsDefined = Boolean(errorLike && errMsgMatcher);
163
259
 
164
- let matcherRelation = "including";
165
- if (errMsgMatcher instanceof RegExp) {
166
- matcherRelation = "matching";
260
+ return reason;
261
+ }
262
+ );
263
+
264
+ transferPromiseness(this, derivedPromise);
265
+ return this;
266
+ });
267
+
268
+ property('eventually', function () {
269
+ utils.flag(this, 'eventually', true);
270
+ return this;
271
+ });
272
+
273
+ method('notify', function (done) {
274
+ doNotify(getBasePromise(this), done);
275
+ return this;
276
+ });
277
+
278
+ method('become', function (value, message) {
279
+ return this.eventually.deep.equal(value, message);
280
+ });
281
+
282
+ // ### `eventually`
283
+
284
+ // We need to be careful not to trigger any getters, thus `Object.getOwnPropertyDescriptor` usage.
285
+ const methodNames = propertyNames.filter((name) => {
286
+ return name !== 'assert' && typeof propertyDescs[name].value === 'function';
287
+ });
288
+
289
+ methodNames.forEach((methodName) => {
290
+ Assertion.overwriteMethod(
291
+ methodName,
292
+ (originalMethod) =>
293
+ function () {
294
+ return doAsserterAsyncAndAddThen(originalMethod, this, arguments);
167
295
  }
168
-
169
- const derivedPromise = getBasePromise(this).then(
170
- value => {
171
- let assertionMessage = null;
172
- let expected = null;
173
-
174
- if (errorLike) {
175
- assertionMessage = "expected promise to be rejected with #{exp} but it was fulfilled with #{act}";
176
- expected = errorLikeName;
177
- } else if (errMsgMatcher) {
178
- assertionMessage = `expected promise to be rejected with an error ${matcherRelation} #{exp} but ` +
179
- `it was fulfilled with #{act}`;
180
- expected = errMsgMatcher;
181
- }
182
-
183
- assertIfNotNegated(this, assertionMessage, { expected, actual: value });
184
- return value;
185
- },
186
- reason => {
187
- const errorLikeCompatible = errorLike && (errorLike instanceof Error ?
188
- checkError.compatibleInstance(reason, errorLike) :
189
- checkError.compatibleConstructor(reason, errorLike));
190
-
191
- const errMsgMatcherCompatible = errMsgMatcher && checkError.compatibleMessage(reason, errMsgMatcher);
192
-
193
- const reasonName = getReasonName(reason);
194
-
195
- if (negate && everyArgIsDefined) {
196
- if (errorLikeCompatible && errMsgMatcherCompatible) {
197
- this.assert(true,
198
- null,
199
- "expected promise not to be rejected with #{exp} but it was rejected " +
200
- "with #{act}",
201
- errorLikeName,
202
- reasonName);
203
- }
204
- } else {
205
- if (errorLike) {
206
- this.assert(errorLikeCompatible,
207
- "expected promise to be rejected with #{exp} but it was rejected with #{act}",
208
- "expected promise not to be rejected with #{exp} but it was rejected " +
209
- "with #{act}",
210
- errorLikeName,
211
- reasonName);
212
- }
213
-
214
- if (errMsgMatcher) {
215
- this.assert(errMsgMatcherCompatible,
216
- `expected promise to be rejected with an error ${matcherRelation} #{exp} but got ` +
217
- `#{act}`,
218
- `expected promise not to be rejected with an error ${matcherRelation} #{exp}`,
219
- errMsgMatcher,
220
- checkError.getMessage(reason));
221
- }
222
- }
223
-
224
- return reason;
225
- }
226
- );
227
-
228
- module.exports.transferPromiseness(this, derivedPromise);
229
- return this;
230
- });
231
-
232
- property("eventually", function () {
233
- utils.flag(this, "eventually", true);
234
- return this;
235
- });
236
-
237
- method("notify", function (done) {
238
- doNotify(getBasePromise(this), done);
239
- return this;
240
- });
241
-
242
- method("become", function (value, message) {
243
- return this.eventually.deep.equal(value, message);
244
- });
245
-
246
- // ### `eventually`
247
-
248
- // We need to be careful not to trigger any getters, thus `Object.getOwnPropertyDescriptor` usage.
249
- const methodNames = propertyNames.filter(name => {
250
- return name !== "assert" && typeof propertyDescs[name].value === "function";
251
- });
252
-
253
- methodNames.forEach(methodName => {
254
- Assertion.overwriteMethod(methodName, originalMethod => function () {
296
+ );
297
+ });
298
+
299
+ const getterNames = propertyNames.filter((name) => {
300
+ return name !== '_obj' && typeof propertyDescs[name].get === 'function';
301
+ });
302
+
303
+ getterNames.forEach((getterName) => {
304
+ // Chainable methods are things like `an`, which can work both for `.should.be.an.instanceOf` and as
305
+ // `should.be.an("object")`. We need to handle those specially.
306
+ const isChainableMethod = Object.prototype.hasOwnProperty.call(
307
+ Assertion.prototype.__methods,
308
+ getterName
309
+ );
310
+
311
+ if (isChainableMethod) {
312
+ Assertion.overwriteChainableMethod(
313
+ getterName,
314
+ (originalMethod) =>
315
+ function () {
255
316
  return doAsserterAsyncAndAddThen(originalMethod, this, arguments);
256
- });
257
- });
258
-
259
- const getterNames = propertyNames.filter(name => {
260
- return name !== "_obj" && typeof propertyDescs[name].get === "function";
261
- });
262
-
263
- getterNames.forEach(getterName => {
264
- // Chainable methods are things like `an`, which can work both for `.should.be.an.instanceOf` and as
265
- // `should.be.an("object")`. We need to handle those specially.
266
- const isChainableMethod = Assertion.prototype.__methods.hasOwnProperty(getterName);
267
-
268
- if (isChainableMethod) {
269
- Assertion.overwriteChainableMethod(
270
- getterName,
271
- originalMethod => function () {
272
- return doAsserterAsyncAndAddThen(originalMethod, this, arguments);
273
- },
274
- originalGetter => function () {
275
- return doAsserterAsyncAndAddThen(originalGetter, this);
276
- }
317
+ },
318
+ (originalGetter) =>
319
+ function () {
320
+ return doAsserterAsyncAndAddThen(originalGetter, this);
321
+ }
322
+ );
323
+ } else {
324
+ Assertion.overwriteProperty(
325
+ getterName,
326
+ (originalGetter) =>
327
+ function () {
328
+ return proxifyIfSupported(
329
+ doAsserterAsyncAndAddThen(originalGetter, this)
277
330
  );
278
- } else {
279
- Assertion.overwriteProperty(getterName, originalGetter => function () {
280
- return proxifyIfSupported(doAsserterAsyncAndAddThen(originalGetter, this));
281
- });
282
- }
283
- });
284
-
285
- function doAsserterAsyncAndAddThen(asserter, assertion, args) {
286
- // Since we're intercepting all methods/properties, we need to just pass through if they don't want
287
- // `eventually`, or if we've already fulfilled the promise (see below).
288
- if (!utils.flag(assertion, "eventually")) {
289
- asserter.apply(assertion, args);
290
- return assertion;
291
- }
292
-
293
- const derivedPromise = getBasePromise(assertion).then(value => {
294
- // Set up the environment for the asserter to actually run: `_obj` should be the fulfillment value, and
295
- // now that we have the value, we're no longer in "eventually" mode, so we won't run any of this code,
296
- // just the base Chai code that we get to via the short-circuit above.
297
- assertion._obj = value;
298
- utils.flag(assertion, "eventually", false);
299
-
300
- return args ? module.exports.transformAsserterArgs(args) : args;
301
- }).then(newArgs => {
302
- asserter.apply(assertion, newArgs);
303
-
304
- // Because asserters, for example `property`, can change the value of `_obj` (i.e. change the "object"
305
- // flag), we need to communicate this value change to subsequent chained asserters. Since we build a
306
- // promise chain paralleling the asserter chain, we can use it to communicate such changes.
307
- return assertion._obj;
308
- });
309
-
310
- module.exports.transferPromiseness(assertion, derivedPromise);
311
- return assertion;
331
+ }
332
+ );
333
+ }
334
+ });
335
+
336
+ function doAsserterAsyncAndAddThen(asserter, assertion, args) {
337
+ // Since we're intercepting all methods/properties, we need to just pass through if they don't want
338
+ // `eventually`, or if we've already fulfilled the promise (see below).
339
+ if (!utils.flag(assertion, 'eventually')) {
340
+ asserter.apply(assertion, args);
341
+ return assertion;
312
342
  }
313
343
 
314
- // ### Now use the `Assertion` framework to build an `assert` interface.
315
- const originalAssertMethods = Object.getOwnPropertyNames(assert).filter(propName => {
316
- return typeof assert[propName] === "function";
317
- });
318
-
319
- assert.isFulfilled = (promise, message) => (new Assertion(promise, message)).to.be.fulfilled;
320
-
321
- assert.isRejected = (promise, errorLike, errMsgMatcher, message) => {
322
- const assertion = new Assertion(promise, message);
323
- return assertion.to.be.rejectedWith(errorLike, errMsgMatcher, message);
324
- };
325
-
326
- assert.becomes = (promise, value, message) => assert.eventually.deepEqual(promise, value, message);
327
-
328
- assert.doesNotBecome = (promise, value, message) => assert.eventually.notDeepEqual(promise, value, message);
329
-
330
- assert.eventually = {};
331
- originalAssertMethods.forEach(assertMethodName => {
332
- assert.eventually[assertMethodName] = function (promise) {
333
- const otherArgs = Array.prototype.slice.call(arguments, 1);
334
-
335
- let customRejectionHandler;
336
- const message = arguments[assert[assertMethodName].length - 1];
337
- if (typeof message === "string") {
338
- customRejectionHandler = reason => {
339
- throw new chai.AssertionError(`${message}\n\nOriginal reason: ${utils.inspect(reason)}`);
340
- };
341
- }
342
-
343
- const returnedPromise = promise.then(
344
- fulfillmentValue => assert[assertMethodName].apply(assert, [fulfillmentValue].concat(otherArgs)),
345
- customRejectionHandler
346
- );
347
-
348
- returnedPromise.notify = done => {
349
- doNotify(returnedPromise, done);
350
- };
351
-
352
- return returnedPromise;
344
+ const derivedPromise = getBasePromise(assertion)
345
+ .then((value) => {
346
+ // Set up the environment for the asserter to actually run: `_obj` should be the fulfillment value, and
347
+ // now that we have the value, we're no longer in "eventually" mode, so we won't run any of this code,
348
+ // just the base Chai code that we get to via the short-circuit above.
349
+ assertion._obj = value;
350
+ utils.flag(assertion, 'eventually', false);
351
+
352
+ return args ? transformAsserterArgs(args) : args;
353
+ })
354
+ .then((newArgs) => {
355
+ asserter.apply(assertion, newArgs);
356
+
357
+ // Because asserters, for example `property`, can change the value of `_obj` (i.e. change the "object"
358
+ // flag), we need to communicate this value change to subsequent chained asserters. Since we build a
359
+ // promise chain paralleling the asserter chain, we can use it to communicate such changes.
360
+ return assertion._obj;
361
+ });
362
+
363
+ transferPromiseness(assertion, derivedPromise);
364
+ return assertion;
365
+ }
366
+
367
+ // ### Now use the `Assertion` framework to build an `assert` interface.
368
+ const originalAssertMethods = Object.getOwnPropertyNames(assert).filter(
369
+ (propName) => {
370
+ return typeof assert[propName] === 'function';
371
+ }
372
+ );
373
+
374
+ assert.isFulfilled = (promise, message) =>
375
+ new Assertion(promise, message).to.be.fulfilled;
376
+
377
+ assert.isRejected = (promise, errorLike, errMsgMatcher, message) => {
378
+ const assertion = new Assertion(promise, message);
379
+ return assertion.to.be.rejectedWith(errorLike, errMsgMatcher, message);
380
+ };
381
+
382
+ assert.becomes = (promise, value, message) =>
383
+ assert.eventually.deepEqual(promise, value, message);
384
+
385
+ assert.doesNotBecome = (promise, value, message) =>
386
+ assert.eventually.notDeepEqual(promise, value, message);
387
+
388
+ assert.eventually = {};
389
+ originalAssertMethods.forEach((assertMethodName) => {
390
+ assert.eventually[assertMethodName] = function (promise) {
391
+ const otherArgs = Array.prototype.slice.call(arguments, 1);
392
+
393
+ let customRejectionHandler;
394
+ const message = arguments[assert[assertMethodName].length - 1];
395
+ if (typeof message === 'string') {
396
+ customRejectionHandler = (reason) => {
397
+ throw new chai.AssertionError(
398
+ `${message}\n\nOriginal reason: ${utils.inspect(reason)}`
399
+ );
353
400
  };
354
- });
355
- };
356
-
357
- module.exports.transferPromiseness = (assertion, promise) => {
358
- assertion.then = promise.then.bind(promise);
359
- };
360
-
361
- module.exports.transformAsserterArgs = values => values;
401
+ }
402
+
403
+ const returnedPromise = promise.then(
404
+ (fulfillmentValue) =>
405
+ assert[assertMethodName].apply(
406
+ assert,
407
+ [fulfillmentValue].concat(otherArgs)
408
+ ),
409
+ customRejectionHandler
410
+ );
411
+
412
+ returnedPromise.notify = (done) => {
413
+ doNotify(returnedPromise, done);
414
+ };
415
+
416
+ return returnedPromise;
417
+ };
418
+ });
419
+ }
420
+
421
+ function defaultTransferPromiseness(assertion, promise) {
422
+ assertion.then = promise.then.bind(promise);
423
+ }
424
+
425
+ function defaultTransformAsserterArgs(values) {
426
+ return values;
427
+ }
428
+
429
+ let customTransferPromiseness;
430
+ let customTransformAsserterArgs;
431
+
432
+ export function setTransferPromiseness(fn) {
433
+ customTransferPromiseness = fn || defaultTransferPromiseness;
434
+ }
435
+
436
+ export function setTransformAsserterArgs(fn) {
437
+ customTransformAsserterArgs = fn || defaultTransformAsserterArgs;
438
+ }
439
+
440
+ export function transferPromiseness(assertion, promise) {
441
+ if (customTransferPromiseness) {
442
+ customTransferPromiseness(assertion, promise);
443
+ } else {
444
+ defaultTransferPromiseness(assertion, promise);
445
+ }
446
+ }
447
+
448
+ export function transformAsserterArgs(values) {
449
+ if (customTransformAsserterArgs) {
450
+ return customTransformAsserterArgs(values);
451
+ }
452
+ return defaultTransformAsserterArgs(values);
453
+ }
package/package.json CHANGED
@@ -1,5 +1,6 @@
1
1
  {
2
2
  "name": "chai-as-promised",
3
+ "type": "module",
3
4
  "description": "Extends Chai with assertions about promises.",
4
5
  "keywords": [
5
6
  "chai",
@@ -11,30 +12,36 @@
11
12
  "promises",
12
13
  "promises-aplus"
13
14
  ],
14
- "version": "7.1.2",
15
+ "version": "8.0.0",
15
16
  "author": "Domenic Denicola <d@domenic.me> (https://domenic.me)",
16
17
  "license": "WTFPL",
17
- "repository": "domenic/chai-as-promised",
18
+ "repository": {
19
+ "type": "git",
20
+ "url": "git+https://github.com/chaijs/chai-as-promised.git"
21
+ },
18
22
  "main": "./lib/chai-as-promised.js",
23
+ "exports": {
24
+ ".": "./lib/chai-as-promised.js"
25
+ },
19
26
  "files": [
20
27
  "lib"
21
28
  ],
22
29
  "scripts": {
23
- "test": "mocha",
24
- "test-travis": "npm install chai@$CHAI_VERSION && npm test",
30
+ "test": "c8 mocha",
25
31
  "lint": "eslint .",
26
- "cover": "istanbul cover node_modules/mocha/bin/_mocha && opener ./coverage/lcov-report/lib/chai-as-promised.js.html"
32
+ "format": "prettier --write lib test"
27
33
  },
28
34
  "dependencies": {
29
- "check-error": "^1.0.2"
35
+ "check-error": "^2.0.0"
30
36
  },
31
37
  "peerDependencies": {
32
38
  "chai": ">= 2.1.2 < 6"
33
39
  },
34
40
  "devDependencies": {
35
- "chai": "^4.0.2",
36
- "eslint": "^3.19.0",
37
- "istanbul": "0.4.5",
38
- "mocha": "^3.4.2"
41
+ "c8": "^9.1.0",
42
+ "chai": "^5.1.0",
43
+ "eslint": "^8.57.0",
44
+ "mocha": "^10.4.0",
45
+ "prettier": "^3.2.5"
39
46
  }
40
47
  }
package/LICENSE.txt DELETED
@@ -1,19 +0,0 @@
1
- Copyright © 2012–2016 Domenic Denicola <d@domenic.me>
2
-
3
- This work is free. You can redistribute it and/or modify it under the
4
- terms of the Do What The Fuck You Want To Public License, Version 2,
5
- as published by Sam Hocevar. See below for more details.
6
-
7
- DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
8
- Version 2, December 2004
9
-
10
- Copyright (C) 2004 Sam Hocevar <sam@hocevar.net>
11
-
12
- Everyone is permitted to copy and distribute verbatim or modified
13
- copies of this license document, and changing it is allowed as long
14
- as the name is changed.
15
-
16
- DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
17
- TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
18
-
19
- 0. You just DO WHAT THE FUCK YOU WANT TO.