konacha-chai-matchers 0.1.5 → 0.1.6
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.
- data/VERSIONS +5 -5
- data/lib/konacha-chai-matchers/library.rb +4 -0
- data/lib/konacha-chai-matchers/version.rb +1 -1
- data/vendor/assets/javascripts/chai-as-promised.js +286 -324
- data/vendor/assets/javascripts/chai-changes.js +14 -6
- data/vendor/assets/javascripts/chai-jquery.js +23 -3
- data/vendor/assets/javascripts/mocha-as-promised.js +11 -4
- data/vendor/assets/javascripts/sinon.js +485 -283
- metadata +21 -29
@@ -1,4 +1,4 @@
|
|
1
|
-
(function (
|
1
|
+
(function () {
|
2
2
|
"use strict";
|
3
3
|
|
4
4
|
// Module systems magic dance.
|
@@ -12,122 +12,133 @@
|
|
12
12
|
return chaiAsPromised;
|
13
13
|
});
|
14
14
|
} else {
|
15
|
+
/*global self: false */
|
16
|
+
|
15
17
|
// Other environment (usually <script> tag): plug in to global chai instance directly.
|
16
18
|
chai.use(chaiAsPromised);
|
19
|
+
|
20
|
+
// Expose as a property of the global object so that consumers can configure the `transferPromiseness` property.
|
21
|
+
self.chaiAsPromised = chaiAsPromised;
|
17
22
|
}
|
18
|
-
}(function chaiAsPromised(chai, utils) {
|
19
|
-
"use strict";
|
20
23
|
|
21
|
-
|
22
|
-
|
24
|
+
chaiAsPromised.transferPromiseness = function (assertion, promise) {
|
25
|
+
assertion.then = promise.then.bind(promise);
|
26
|
+
};
|
23
27
|
|
24
|
-
function
|
25
|
-
|
26
|
-
|
28
|
+
function chaiAsPromised(chai, utils) {
|
29
|
+
var Assertion = chai.Assertion;
|
30
|
+
var assert = chai.assert;
|
31
|
+
|
32
|
+
function isJQueryPromise(thenable) {
|
33
|
+
return typeof thenable.always === "function" &&
|
34
|
+
typeof thenable.done === "function" &&
|
35
|
+
typeof thenable.fail === "function" &&
|
36
|
+
typeof thenable.pipe === "function" &&
|
37
|
+
typeof thenable.progress === "function" &&
|
38
|
+
typeof thenable.state === "function";
|
27
39
|
}
|
28
|
-
|
29
|
-
|
40
|
+
|
41
|
+
function assertIsAboutPromise(assertion) {
|
42
|
+
if (typeof assertion._obj.then !== "function") {
|
43
|
+
throw new TypeError(utils.inspect(assertion._obj) + " is not a thenable.");
|
44
|
+
}
|
45
|
+
if (isJQueryPromise(assertion._obj)) {
|
46
|
+
throw new TypeError("Chai as Promised is incompatible with jQuery's thenables, sorry! Please use a " +
|
47
|
+
"Promises/A+ compatible library (see http://promisesaplus.com/).");
|
48
|
+
}
|
30
49
|
}
|
31
|
-
}
|
32
50
|
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
51
|
+
function method(name, asserter) {
|
52
|
+
utils.addMethod(Assertion.prototype, name, function () {
|
53
|
+
assertIsAboutPromise(this);
|
54
|
+
return asserter.apply(this, arguments);
|
55
|
+
});
|
56
|
+
}
|
39
57
|
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
58
|
+
function property(name, asserter) {
|
59
|
+
utils.addProperty(Assertion.prototype, name, function () {
|
60
|
+
assertIsAboutPromise(this);
|
61
|
+
return asserter.apply(this, arguments);
|
62
|
+
});
|
63
|
+
}
|
46
64
|
|
47
|
-
|
48
|
-
|
49
|
-
|
65
|
+
function doNotify(promise, done) {
|
66
|
+
promise.then(function () { done(); }, done);
|
67
|
+
}
|
50
68
|
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
}
|
55
|
-
}
|
69
|
+
// These are for clarity and to bypass Chai refusing to allow `undefined` as actual when used with `assert`.
|
70
|
+
function assertIfNegated(assertion, message, extra) {
|
71
|
+
assertion.assert(true, null, message, extra.expected, extra.actual);
|
72
|
+
}
|
56
73
|
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
var transformedPromise = assertion._obj.then(
|
62
|
-
function (value) {
|
63
|
-
if (utils.flag(assertion, "negate")) {
|
64
|
-
// If we're negated, `this.assert`'s behavior is actually flipped, so `this.assert(true, ...)` will
|
65
|
-
// throw an error, as desired.
|
66
|
-
assertion.assert(true, null, "expected promise to be rejected but it was fulfilled with " +
|
67
|
-
utils.inspect(value));
|
68
|
-
}
|
74
|
+
function assertIfNotNegated(assertion, message, extra) {
|
75
|
+
assertion.assert(false, message, null, extra.expected, extra.actual);
|
76
|
+
}
|
69
77
|
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
}
|
78
|
-
);
|
78
|
+
function getBasePromise(assertion) {
|
79
|
+
// We need to chain subsequent asserters on top of ones in the chain already (consider
|
80
|
+
// `eventually.have.property("foo").that.equals("bar")`), only running them after the existing ones pass.
|
81
|
+
// So the first base-promise is `assertion._obj`, but after that we use the assertions themselves, i.e.
|
82
|
+
// previously derived promises, to chain off of.
|
83
|
+
return typeof assertion.then === "function" ? assertion : assertion._obj;
|
84
|
+
}
|
79
85
|
|
80
|
-
|
81
|
-
}
|
86
|
+
// Grab these first, before we modify `Assertion.prototype`.
|
82
87
|
|
83
|
-
|
84
|
-
// THIS SHIT IS COMPLICATED. Best illustrated by exhaustive example.
|
85
|
-
////////////////////////////////////////////////////////////////////
|
86
|
-
// `fulfilledPromise.should.be.rejected`:
|
87
|
-
// `onOriginalFulfilled` → `this.assert(false, …)` throws → rejects
|
88
|
-
// `fulfilledPromise.should.not.be.rejected`:
|
89
|
-
// `onOriginalFulfilled` → `this.assert(false, …)` does nothing → fulfills
|
90
|
-
// `rejectedPromise.should.be.rejected`:
|
91
|
-
// `onOriginalRejected` does nothing relevant → fulfills
|
92
|
-
// `rejectedPromise.should.not.be.rejected`:
|
93
|
-
// `onOriginalRejected` → `this.assert(true, …)` throws → rejects
|
94
|
-
// `rejectedPromise.should.be.rejected.with(xxx)`:
|
95
|
-
// `onOriginalRejected` saves `rejectionReason` → fulfills →
|
96
|
-
// `with(xxx)` called → `onTransformedFulfilled` → assert about xxx → fulfills/rejects based on asserts
|
97
|
-
// `rejectedPromise.should.not.be.rejected.with(xxx)`:
|
98
|
-
// `onOriginalRejected` saves `rejectionReason`, `this.assert(true, …)` throws → rejects →
|
99
|
-
// `with(xxx)` called → `onTransformedRejected` → assert about xxx → fulfills/rejects based on asserts
|
100
|
-
// `fulfilledPromise.should.be.rejected.with(xxx)`:
|
101
|
-
// `onOriginalFulfilled` → `this.assert(false, …)` throws → rejects →
|
102
|
-
// `with(xxx)` called → `onTransformedRejected` → `this.assert(false, …)` throws → rejected
|
103
|
-
// `fulfilledPromise.should.not.be.rejected.with(xxx)`:
|
104
|
-
// `onOriginalFulfilled` → `this.assert(false, …)` does nothing → fulfills →
|
105
|
-
// `with(xxx)` called → `onTransformedFulfilled` → fulfills
|
106
|
-
|
107
|
-
/*jshint validthis:true */
|
108
|
-
var assertion = this;
|
109
|
-
var rejectionReason = null;
|
110
|
-
|
111
|
-
function onOriginalFulfilled(value) {
|
112
|
-
assertion.assert(false, "expected promise to be rejected but it was fulfilled with " + utils.inspect(value));
|
113
|
-
}
|
88
|
+
var propertyNames = Object.getOwnPropertyNames(Assertion.prototype);
|
114
89
|
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
90
|
+
var propertyDescs = {};
|
91
|
+
propertyNames.forEach(function (name) {
|
92
|
+
propertyDescs[name] = Object.getOwnPropertyDescriptor(Assertion.prototype, name);
|
93
|
+
});
|
119
94
|
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
95
|
+
property("fulfilled", function () {
|
96
|
+
var that = this;
|
97
|
+
var derivedPromise = getBasePromise(that).then(
|
98
|
+
function (value) {
|
99
|
+
that._obj = value;
|
100
|
+
assertIfNegated(that,
|
101
|
+
"expected promise not to be fulfilled but it was fulfilled with #{act}",
|
102
|
+
{ actual: value });
|
103
|
+
return value;
|
104
|
+
},
|
105
|
+
function (reason) {
|
106
|
+
assertIfNotNegated(that,
|
107
|
+
"expected promise to be fulfilled but it was rejected with #{act}",
|
108
|
+
{ actual: reason });
|
109
|
+
}
|
110
|
+
);
|
124
111
|
|
125
|
-
|
126
|
-
|
127
|
-
|
112
|
+
chaiAsPromised.transferPromiseness(that, derivedPromise);
|
113
|
+
});
|
114
|
+
|
115
|
+
property("rejected", function () {
|
116
|
+
var that = this;
|
117
|
+
var derivedPromise = getBasePromise(that).then(
|
118
|
+
function (value) {
|
119
|
+
that._obj = value;
|
120
|
+
assertIfNotNegated(that,
|
121
|
+
"expected promise to be rejected but it was fulfilled with #{act}",
|
122
|
+
{ actual: value });
|
123
|
+
return value;
|
124
|
+
},
|
125
|
+
function (reason) {
|
126
|
+
assertIfNegated(that,
|
127
|
+
"expected promise not to be rejected but it was rejected with #{act}",
|
128
|
+
{ actual: reason });
|
129
|
+
|
130
|
+
// Return the reason, transforming this into a fulfillment, to allow further assertions, e.g.
|
131
|
+
// `promise.should.be.rejected.and.eventually.equal("reason")`.
|
132
|
+
return reason;
|
133
|
+
}
|
134
|
+
);
|
128
135
|
|
129
|
-
|
136
|
+
chaiAsPromised.transferPromiseness(that, derivedPromise);
|
137
|
+
});
|
138
|
+
|
139
|
+
method("rejectedWith", function (Constructor, message) {
|
130
140
|
var desiredReason = null;
|
141
|
+
var constructorName = null;
|
131
142
|
|
132
143
|
if (Constructor instanceof RegExp || typeof Constructor === "string") {
|
133
144
|
message = Constructor;
|
@@ -136,272 +147,223 @@
|
|
136
147
|
desiredReason = Constructor;
|
137
148
|
Constructor = null;
|
138
149
|
message = null;
|
139
|
-
}
|
140
|
-
|
141
|
-
var messageVerb = null;
|
142
|
-
var messageIsGood = null;
|
143
|
-
|
144
|
-
if (message instanceof RegExp) {
|
145
|
-
messageVerb = "matching";
|
146
|
-
messageIsGood = function () {
|
147
|
-
return message.test(rejectionReason.message);
|
148
|
-
};
|
150
|
+
} else if (typeof Constructor === "function") {
|
151
|
+
constructorName = (new Constructor()).name;
|
149
152
|
} else {
|
150
|
-
|
151
|
-
messageIsGood = function () {
|
152
|
-
return rejectionReason && rejectionReason.message.indexOf(message) !== -1;
|
153
|
-
};
|
154
|
-
}
|
155
|
-
|
156
|
-
function constructorIsGood() {
|
157
|
-
return rejectionReason instanceof Constructor;
|
158
|
-
}
|
159
|
-
|
160
|
-
function matchesDesiredReason() {
|
161
|
-
return rejectionReason === desiredReason;
|
153
|
+
Constructor = null;
|
162
154
|
}
|
163
155
|
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
"expected promise to be rejected with " + utils.inspect(desiredReason) + " but " +
|
170
|
-
"it was rejected with " + utils.inspect(rejectionReason));
|
171
|
-
}
|
156
|
+
var that = this;
|
157
|
+
var derivedPromise = getBasePromise(that).then(
|
158
|
+
function (value) {
|
159
|
+
var assertionMessage = null;
|
160
|
+
var expected = null;
|
172
161
|
|
173
162
|
if (Constructor) {
|
174
|
-
|
175
|
-
|
176
|
-
|
163
|
+
assertionMessage = "expected promise to be rejected with #{exp} but it was fulfilled with " +
|
164
|
+
"#{act}";
|
165
|
+
expected = constructorName;
|
166
|
+
} else if (message) {
|
167
|
+
var verb = message instanceof RegExp ? "matching" : "including";
|
168
|
+
assertionMessage = "expected promise to be rejected with an error " + verb + " #{exp} but it " +
|
169
|
+
"was fulfilled with #{act}";
|
170
|
+
expected = message;
|
171
|
+
} else if (desiredReason) {
|
172
|
+
assertionMessage = "expected promise to be rejected with #{exp} but it was fulfilled with " +
|
173
|
+
"#{act}";
|
174
|
+
expected = desiredReason;
|
177
175
|
}
|
178
176
|
|
179
|
-
|
180
|
-
assertion.assert(messageIsGood(),
|
181
|
-
"expected promise to be rejected with an error " + messageVerb + " " + message +
|
182
|
-
" but got " + utils.inspect(rejectionReason && rejectionReason.message));
|
183
|
-
}
|
184
|
-
}
|
185
|
-
}
|
186
|
-
|
187
|
-
function onTransformedRejected() {
|
188
|
-
if (utils.flag(assertion, "negate")) {
|
189
|
-
if (desiredReason) {
|
190
|
-
assertion.assert(matchesDesiredReason(),
|
191
|
-
null,
|
192
|
-
"expected promise to not be rejected with " + utils.inspect(desiredReason));
|
193
|
-
}
|
177
|
+
that._obj = value;
|
194
178
|
|
179
|
+
assertIfNotNegated(that, assertionMessage, { expected: expected, actual: value });
|
180
|
+
},
|
181
|
+
function (reason) {
|
195
182
|
if (Constructor) {
|
196
|
-
|
197
|
-
|
198
|
-
"expected promise to
|
199
|
-
|
200
|
-
|
201
|
-
if (message) {
|
202
|
-
assertion.assert(messageIsGood(),
|
203
|
-
null,
|
204
|
-
"expected promise to be not be rejected with an error " + messageVerb + " " +
|
205
|
-
message);
|
206
|
-
}
|
207
|
-
} else {
|
208
|
-
if (desiredReason) {
|
209
|
-
assertion.assert(false,
|
210
|
-
"expected promise to be rejected with " + utils.inspect(desiredReason) +
|
211
|
-
" but it was fulfilled");
|
183
|
+
that.assert(reason instanceof Constructor,
|
184
|
+
"expected promise to be rejected with #{exp} but it was rejected with #{act}",
|
185
|
+
"expected promise not to be rejected with #{exp} but it was rejected with #{act}",
|
186
|
+
constructorName,
|
187
|
+
reason);
|
212
188
|
}
|
213
189
|
|
214
|
-
|
215
|
-
|
216
|
-
|
190
|
+
var reasonMessage = utils.type(reason) === "object" && "message" in reason ?
|
191
|
+
reason.message :
|
192
|
+
"" + reason;
|
193
|
+
if (message && reasonMessage !== null && reasonMessage !== undefined) {
|
194
|
+
if (message instanceof RegExp) {
|
195
|
+
that.assert(message.test(reasonMessage),
|
196
|
+
"expected promise to be rejected with an error matching #{exp} but got #{act}",
|
197
|
+
"expected promise not to be rejected with an error matching #{exp}",
|
198
|
+
message,
|
199
|
+
reasonMessage);
|
200
|
+
}
|
201
|
+
if (typeof message === "string") {
|
202
|
+
that.assert(reasonMessage.indexOf(message) !== -1,
|
203
|
+
"expected promise to be rejected with an error including #{exp} but got #{act}",
|
204
|
+
"expected promise not to be rejected with an error including #{exp}",
|
205
|
+
message,
|
206
|
+
reasonMessage);
|
207
|
+
}
|
217
208
|
}
|
218
209
|
|
219
|
-
if (
|
220
|
-
|
221
|
-
|
210
|
+
if (desiredReason) {
|
211
|
+
that.assert(reason === desiredReason,
|
212
|
+
"expected promise to be rejected with #{exp} but it was rejected with #{act}",
|
213
|
+
"expected promise not to be rejected with #{exp}",
|
214
|
+
desiredReason,
|
215
|
+
reason);
|
222
216
|
}
|
223
217
|
}
|
224
|
-
}
|
225
|
-
|
226
|
-
return makeAssertionPromise(
|
227
|
-
transformedPromise.then(onTransformedFulfilled, onTransformedRejected),
|
228
|
-
assertion
|
229
218
|
);
|
230
|
-
}
|
231
|
-
|
232
|
-
var derivedPromise = assertion._obj.then(onOriginalFulfilled, onOriginalRejected);
|
233
|
-
var transformedPromise = makeAssertionPromise(derivedPromise, assertion);
|
234
|
-
Object.defineProperty(transformedPromise, "with", { enumerable: true, configurable: true, value: withMethod });
|
235
|
-
|
236
|
-
return transformedPromise;
|
237
|
-
}
|
238
|
-
|
239
|
-
function isChaiAsPromisedAsserter(asserterName) {
|
240
|
-
return ["fulfilled", "rejected", "broken", "eventually", "become"].indexOf(asserterName) !== -1;
|
241
|
-
}
|
242
219
|
|
243
|
-
|
244
|
-
|
245
|
-
// The previous assertion promise might have picked up some flags while waiting for fulfillment.
|
246
|
-
utils.transferFlags(previousAssertionPromise, currentAssertionPromise);
|
247
|
-
|
248
|
-
// Replace the object flag with the fulfillment value, so that doAsserter can operate properly.
|
249
|
-
utils.flag(currentAssertionPromise, "object", fulfillmentValue);
|
220
|
+
chaiAsPromised.transferPromiseness(that, derivedPromise);
|
221
|
+
});
|
250
222
|
|
251
|
-
|
252
|
-
|
223
|
+
property("eventually", function () {
|
224
|
+
utils.flag(this, "eventually", true);
|
253
225
|
});
|
254
|
-
return makeAssertionPromise(promiseToDoAsserter, currentAssertionPromise);
|
255
|
-
}
|
256
226
|
|
257
|
-
|
258
|
-
|
259
|
-
|
227
|
+
method("notify", function (done) {
|
228
|
+
doNotify(getBasePromise(this), done);
|
229
|
+
});
|
260
230
|
|
261
|
-
|
262
|
-
|
231
|
+
method("become", function (value) {
|
232
|
+
return this.eventually.deep.equal(value);
|
233
|
+
});
|
263
234
|
|
264
|
-
|
265
|
-
//
|
266
|
-
assertionPromise.assert = function () {
|
267
|
-
return Assertion.prototype.assert.apply(assertionPromise, arguments);
|
268
|
-
};
|
235
|
+
////////
|
236
|
+
// `eventually`
|
269
237
|
|
270
|
-
|
238
|
+
// We need to be careful not to trigger any getters, thus `Object.getOwnPropertyDescriptor` usage.
|
239
|
+
var methodNames = propertyNames.filter(function (name) {
|
240
|
+
return name !== "assert" && typeof propertyDescs[name].value === "function";
|
241
|
+
});
|
271
242
|
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
243
|
+
methodNames.forEach(function (methodName) {
|
244
|
+
Assertion.overwriteMethod(methodName, function (originalMethod) {
|
245
|
+
return function () {
|
246
|
+
doAsserterAsyncAndAddThen(originalMethod, this, arguments);
|
247
|
+
};
|
248
|
+
});
|
249
|
+
});
|
279
250
|
|
280
|
-
|
281
|
-
|
282
|
-
|
283
|
-
throw new Error("Cannot use Chai as Promised asserters more than once in an assertion.");
|
284
|
-
});
|
285
|
-
return;
|
286
|
-
}
|
251
|
+
var getterNames = propertyNames.filter(function (name) {
|
252
|
+
return name !== "_obj" && typeof propertyDescs[name].get === "function";
|
253
|
+
});
|
287
254
|
|
288
|
-
|
289
|
-
|
290
|
-
|
291
|
-
//
|
292
|
-
//
|
293
|
-
var
|
294
|
-
|
295
|
-
|
296
|
-
|
297
|
-
|
298
|
-
|
299
|
-
|
300
|
-
|
301
|
-
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
// Case 2: property asserters. These break down into two subcases: chainable methods, and pure
|
306
|
-
// properties. An example of the former is `a`/`an`: `.should.be.an.instanceOf` vs.
|
307
|
-
// `should.be.an("object")`.
|
308
|
-
var isChainableMethod = false;
|
309
|
-
try {
|
310
|
-
isChainableMethod = typeof propertyDescriptor.get.call({}) === "function";
|
311
|
-
} catch (e) { }
|
312
|
-
|
313
|
-
if (isChainableMethod) {
|
314
|
-
// Case 2A: chainable methods. Recreate the chainable method, but operating on the augmented
|
315
|
-
// promise. We need to copy both the assertion behavior and the chaining behavior, since the
|
316
|
-
// chaining behavior might for example set flags on the object.
|
317
|
-
utils.addChainableMethod(
|
318
|
-
assertionPromise,
|
319
|
-
asserterName,
|
320
|
-
function () {
|
321
|
-
var args = arguments;
|
322
|
-
|
323
|
-
return makeAssertionPromiseToDoAsserter(assertionPromise, baseAssertion, function () {
|
324
|
-
// Due to https://github.com/chaijs/chai/commit/514dd6ce466d7b4110b38345e4073d586c017f3f
|
325
|
-
// we can't use `propertyDescriptor.get().apply`.
|
326
|
-
return Function.prototype.apply.call(propertyDescriptor.get(), assertionPromise, args);
|
327
|
-
});
|
328
|
-
},
|
329
|
-
function () {
|
330
|
-
// As above.
|
331
|
-
return Function.prototype.call.call(propertyDescriptor.get, assertionPromise);
|
255
|
+
getterNames.forEach(function (getterName) {
|
256
|
+
var propertyDesc = propertyDescs[getterName];
|
257
|
+
|
258
|
+
// Chainable methods are things like `an`, which can work both for `.should.be.an.instanceOf` and as
|
259
|
+
// `should.be.an("object")`. We need to handle those specially.
|
260
|
+
var isChainableMethod = false;
|
261
|
+
try {
|
262
|
+
isChainableMethod = typeof propertyDesc.get.call({}) === "function";
|
263
|
+
} catch (e) { }
|
264
|
+
|
265
|
+
if (isChainableMethod) {
|
266
|
+
Assertion.addChainableMethod(
|
267
|
+
getterName,
|
268
|
+
function () {
|
269
|
+
var assertion = this;
|
270
|
+
function originalMethod() {
|
271
|
+
return propertyDesc.get.call(assertion).apply(assertion, arguments);
|
332
272
|
}
|
333
|
-
|
334
|
-
|
335
|
-
|
336
|
-
|
337
|
-
|
338
|
-
|
339
|
-
|
340
|
-
|
341
|
-
|
273
|
+
doAsserterAsyncAndAddThen(originalMethod, this, arguments);
|
274
|
+
},
|
275
|
+
function () {
|
276
|
+
var originalGetter = propertyDesc.get;
|
277
|
+
doAsserterAsyncAndAddThen(originalGetter, this);
|
278
|
+
}
|
279
|
+
);
|
280
|
+
} else {
|
281
|
+
Assertion.overwriteProperty(getterName, function (originalGetter) {
|
282
|
+
return function () {
|
283
|
+
doAsserterAsyncAndAddThen(originalGetter, this);
|
284
|
+
};
|
285
|
+
});
|
342
286
|
}
|
343
287
|
});
|
344
288
|
|
345
|
-
|
346
|
-
|
347
|
-
|
348
|
-
|
349
|
-
|
350
|
-
|
351
|
-
|
352
|
-
property("eventually", function () {
|
353
|
-
return makeAssertionPromise(this._obj, this);
|
354
|
-
});
|
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);
|
294
|
+
}
|
355
295
|
|
356
|
-
|
357
|
-
|
358
|
-
|
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
|
+
asserter.apply(assertion, args);
|
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
|
+
});
|
359
309
|
|
360
|
-
|
361
|
-
|
362
|
-
});
|
310
|
+
chaiAsPromised.transferPromiseness(assertion, derivedPromise);
|
311
|
+
}
|
363
312
|
|
364
|
-
|
365
|
-
|
366
|
-
|
367
|
-
|
313
|
+
///////
|
314
|
+
// Now use the `Assertion` framework to build an `assert` interface.
|
315
|
+
var originalAssertMethods = Object.getOwnPropertyNames(assert).filter(function (propName) {
|
316
|
+
return typeof assert[propName] === "function";
|
317
|
+
});
|
368
318
|
|
369
|
-
|
370
|
-
|
371
|
-
|
319
|
+
assert.isFulfilled = function (promise, message) {
|
320
|
+
return (new Assertion(promise, message)).to.be.fulfilled;
|
321
|
+
};
|
372
322
|
|
373
|
-
|
374
|
-
|
375
|
-
|
376
|
-
|
377
|
-
|
323
|
+
assert.isRejected = function (promise, toTestAgainst, message) {
|
324
|
+
if (typeof toTestAgainst === "string") {
|
325
|
+
message = toTestAgainst;
|
326
|
+
toTestAgainst = undefined;
|
327
|
+
}
|
378
328
|
|
379
|
-
|
329
|
+
var assertion = (new Assertion(promise, message));
|
330
|
+
return toTestAgainst !== undefined ? assertion.to.be.rejectedWith(toTestAgainst) : assertion.to.be.rejected;
|
331
|
+
};
|
380
332
|
|
381
|
-
|
382
|
-
|
383
|
-
|
333
|
+
assert.becomes = function (promise, value) {
|
334
|
+
return assert.eventually.deepEqual(promise, value);
|
335
|
+
};
|
384
336
|
|
385
|
-
|
386
|
-
|
387
|
-
|
388
|
-
var otherArgs = Array.prototype.slice.call(arguments, 1);
|
337
|
+
assert.doesNotBecome = function (promise, value) {
|
338
|
+
return assert.eventually.notDeepEqual(promise, value);
|
339
|
+
};
|
389
340
|
|
390
|
-
|
391
|
-
|
392
|
-
|
341
|
+
assert.eventually = {};
|
342
|
+
originalAssertMethods.forEach(function (assertMethodName) {
|
343
|
+
assert.eventually[assertMethodName] = function (promise) {
|
344
|
+
var otherArgs = Array.prototype.slice.call(arguments, 1);
|
345
|
+
|
346
|
+
var customRejectionHandler;
|
347
|
+
var message = arguments[assert[assertMethodName].length - 1];
|
348
|
+
if (typeof message === "string") {
|
349
|
+
customRejectionHandler = function (reason) {
|
350
|
+
throw new chai.AssertionError(message + "\n\nOriginal reason: " + utils.inspect(reason));
|
351
|
+
};
|
352
|
+
}
|
393
353
|
|
394
|
-
|
395
|
-
|
396
|
-
|
397
|
-
|
398
|
-
|
354
|
+
var returnedPromise = promise.then(
|
355
|
+
function (fulfillmentValue) {
|
356
|
+
return assert[assertMethodName].apply(assert, [fulfillmentValue].concat(otherArgs));
|
357
|
+
},
|
358
|
+
customRejectionHandler
|
359
|
+
);
|
399
360
|
|
400
|
-
|
401
|
-
|
402
|
-
|
361
|
+
returnedPromise.notify = function (done) {
|
362
|
+
doNotify(returnedPromise, done);
|
363
|
+
};
|
403
364
|
|
404
|
-
|
405
|
-
|
406
|
-
|
407
|
-
}
|
365
|
+
return returnedPromise;
|
366
|
+
};
|
367
|
+
});
|
368
|
+
}
|
369
|
+
}());
|