ende 0.4.5 → 0.4.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.
Files changed (81) hide show
  1. checksums.yaml +4 -4
  2. data/lib/assets/javascripts/aura/extensions/devise.js.coffee +0 -2
  3. data/lib/assets/javascripts/aura/extensions/platform.js.coffee +3 -0
  4. data/lib/assets/javascripts/aura/extensions/rivets.js.coffee +17 -1
  5. data/lib/assets/javascripts/aura/extensions/routes.js.coffee +8 -7
  6. data/lib/assets/javascripts/aura/extensions/states.js.coffee +13 -1
  7. data/lib/assets/javascripts/aura/extensions/widget/eventable.js.coffee +4 -2
  8. data/lib/assets/javascripts/config/load_components.js.coffee +19 -12
  9. data/lib/assets/javascripts/ende.js.coffee +33 -12
  10. data/lib/ende/version.rb +1 -1
  11. data/vendor/assets/components/build.css +111 -0
  12. data/vendor/assets/components/ende_build.js +160 -41
  13. data/vendor/components/indefinido-indemma/build/development.js +3 -118
  14. data/vendor/components/indefinido-indemma/build/release.js +39 -4170
  15. data/vendor/components/indefinido-indemma/build/test.js +3 -118
  16. data/vendor/components/indefinido-indemma/lib/record/associable.js +10 -2
  17. data/vendor/components/indefinido-indemma/lib/record/restfulable.js +26 -15
  18. data/vendor/components/indefinido-indemma/lib/record.js +3 -1
  19. data/vendor/components/indefinido-indemma/src/lib/record/associable.coffee +15 -1
  20. data/vendor/components/indefinido-indemma/src/lib/record/restfulable.coffee +37 -12
  21. data/vendor/components/indefinido-indemma/src/lib/record.coffee +3 -1
  22. data/vendor/components/indefinido-observable/.gitignore +15 -0
  23. data/vendor/components/indefinido-observable/.ruby-gemset +1 -0
  24. data/vendor/components/indefinido-observable/.ruby-version +1 -0
  25. data/vendor/components/indefinido-observable/Gemfile +13 -0
  26. data/vendor/components/indefinido-observable/Guardfile +39 -0
  27. data/vendor/components/indefinido-observable/History.md +0 -0
  28. data/vendor/components/indefinido-observable/Readme.md +116 -0
  29. data/vendor/components/indefinido-observable/build/build.js +14798 -0
  30. data/vendor/components/indefinido-observable/build/development.js +339 -0
  31. data/vendor/components/indefinido-observable/build/release.js +14937 -0
  32. data/vendor/components/indefinido-observable/build/test.js +339 -0
  33. data/vendor/components/indefinido-observable/component.json +5 -1
  34. data/vendor/components/indefinido-observable/components/chaijs-chai/component.json +46 -0
  35. data/vendor/components/indefinido-observable/components/chaijs-chai/index.js +1 -0
  36. data/vendor/components/indefinido-observable/components/chaijs-chai/lib/chai/assertion.js +132 -0
  37. data/vendor/components/indefinido-observable/components/chaijs-chai/lib/chai/core/assertions.js +1270 -0
  38. data/vendor/components/indefinido-observable/components/chaijs-chai/lib/chai/error.js +60 -0
  39. data/vendor/components/indefinido-observable/components/chaijs-chai/lib/chai/interface/assert.js +1060 -0
  40. data/vendor/components/indefinido-observable/components/chaijs-chai/lib/chai/interface/expect.js +12 -0
  41. data/vendor/components/indefinido-observable/components/chaijs-chai/lib/chai/interface/should.js +76 -0
  42. data/vendor/components/indefinido-observable/components/chaijs-chai/lib/chai/utils/addChainableMethod.js +94 -0
  43. data/vendor/components/indefinido-observable/components/chaijs-chai/lib/chai/utils/addMethod.js +37 -0
  44. data/vendor/components/indefinido-observable/components/chaijs-chai/lib/chai/utils/addProperty.js +40 -0
  45. data/vendor/components/indefinido-observable/components/chaijs-chai/lib/chai/utils/eql.js +124 -0
  46. data/vendor/components/indefinido-observable/components/chaijs-chai/lib/chai/utils/flag.js +32 -0
  47. data/vendor/components/indefinido-observable/components/chaijs-chai/lib/chai/utils/getActual.js +19 -0
  48. data/vendor/components/indefinido-observable/components/chaijs-chai/lib/chai/utils/getEnumerableProperties.js +25 -0
  49. data/vendor/components/indefinido-observable/components/chaijs-chai/lib/chai/utils/getMessage.js +49 -0
  50. data/vendor/components/indefinido-observable/components/chaijs-chai/lib/chai/utils/getName.js +20 -0
  51. data/vendor/components/indefinido-observable/components/chaijs-chai/lib/chai/utils/getPathValue.js +102 -0
  52. data/vendor/components/indefinido-observable/components/chaijs-chai/lib/chai/utils/getProperties.js +35 -0
  53. data/vendor/components/indefinido-observable/components/chaijs-chai/lib/chai/utils/index.js +108 -0
  54. data/vendor/components/indefinido-observable/components/chaijs-chai/lib/chai/utils/inspect.js +316 -0
  55. data/vendor/components/indefinido-observable/components/chaijs-chai/lib/chai/utils/objDisplay.js +48 -0
  56. data/vendor/components/indefinido-observable/components/chaijs-chai/lib/chai/utils/overwriteMethod.js +51 -0
  57. data/vendor/components/indefinido-observable/components/chaijs-chai/lib/chai/utils/overwriteProperty.js +54 -0
  58. data/vendor/components/indefinido-observable/components/chaijs-chai/lib/chai/utils/test.js +26 -0
  59. data/vendor/components/indefinido-observable/components/chaijs-chai/lib/chai/utils/transferFlags.js +44 -0
  60. data/vendor/components/indefinido-observable/components/chaijs-chai/lib/chai/utils/type.js +45 -0
  61. data/vendor/components/indefinido-observable/components/chaijs-chai/lib/chai.js +79 -0
  62. data/vendor/components/indefinido-observable/components/component-jquery/component.json +14 -0
  63. data/vendor/components/indefinido-observable/components/component-jquery/index.js +9601 -0
  64. data/vendor/components/indefinido-observable/components/kapit-observe-shim/component.json +11 -0
  65. data/vendor/components/indefinido-observable/components/kapit-observe-utils/component.json +13 -0
  66. data/vendor/components/indefinido-observable/karma.conf.js +92 -0
  67. data/vendor/components/indefinido-observable/lib/adapters/rivets.js +3 -1
  68. data/vendor/components/indefinido-observable/lib/observable.js +47 -13
  69. data/vendor/components/indefinido-observable/spec/legacy/observable_spec.js +126 -0
  70. data/vendor/components/indefinido-observable/spec/observable_spec.js +92 -0
  71. data/vendor/components/indefinido-observable/spec/spec_helper.js +8 -0
  72. data/vendor/components/indefinido-observable/spec/vendor/accessors_spec.js +63 -0
  73. data/vendor/components/indefinido-observable/src/lib/adapters/rivets.js.coffee +15 -0
  74. data/vendor/components/indefinido-observable/src/spec/legacy/observable_spec.coffee +132 -0
  75. data/vendor/components/indefinido-observable/src/spec/observable_spec.coffee +85 -0
  76. data/vendor/components/indefinido-observable/src/spec/spec_helper.coffee +5 -0
  77. data/vendor/components/indefinido-observable/src/spec/vendor/accessors_spec.coffee +59 -0
  78. data/vendor/components/indefinido-observable/vendor/shims/accessors.js +71 -9
  79. data/vendor/components/indefinido-observable/vendor/spec/boot.js +104 -0
  80. data/vendor/components/indefinido-observable/vendor/spec/jasmine.js +2054 -0
  81. metadata +58 -2
@@ -0,0 +1,1270 @@
1
+ /*!
2
+ * chai
3
+ * http://chaijs.com
4
+ * Copyright(c) 2011-2013 Jake Luer <jake@alogicalparadox.com>
5
+ * MIT Licensed
6
+ */
7
+
8
+ module.exports = function (chai, _) {
9
+ var Assertion = chai.Assertion
10
+ , toString = Object.prototype.toString
11
+ , flag = _.flag;
12
+
13
+ /**
14
+ * ### Language Chains
15
+ *
16
+ * The following are provide as chainable getters to
17
+ * improve the readability of your assertions. They
18
+ * do not provide an testing capability unless they
19
+ * have been overwritten by a plugin.
20
+ *
21
+ * **Chains**
22
+ *
23
+ * - to
24
+ * - be
25
+ * - been
26
+ * - is
27
+ * - that
28
+ * - and
29
+ * - have
30
+ * - with
31
+ * - at
32
+ * - of
33
+ * - same
34
+ *
35
+ * @name language chains
36
+ * @api public
37
+ */
38
+
39
+ [ 'to', 'be', 'been'
40
+ , 'is', 'and', 'have'
41
+ , 'with', 'that', 'at'
42
+ , 'of', 'same' ].forEach(function (chain) {
43
+ Assertion.addProperty(chain, function () {
44
+ return this;
45
+ });
46
+ });
47
+
48
+ /**
49
+ * ### .not
50
+ *
51
+ * Negates any of assertions following in the chain.
52
+ *
53
+ * expect(foo).to.not.equal('bar');
54
+ * expect(goodFn).to.not.throw(Error);
55
+ * expect({ foo: 'baz' }).to.have.property('foo')
56
+ * .and.not.equal('bar');
57
+ *
58
+ * @name not
59
+ * @api public
60
+ */
61
+
62
+ Assertion.addProperty('not', function () {
63
+ flag(this, 'negate', true);
64
+ });
65
+
66
+ /**
67
+ * ### .deep
68
+ *
69
+ * Sets the `deep` flag, later used by the `equal` and
70
+ * `property` assertions.
71
+ *
72
+ * expect(foo).to.deep.equal({ bar: 'baz' });
73
+ * expect({ foo: { bar: { baz: 'quux' } } })
74
+ * .to.have.deep.property('foo.bar.baz', 'quux');
75
+ *
76
+ * @name deep
77
+ * @api public
78
+ */
79
+
80
+ Assertion.addProperty('deep', function () {
81
+ flag(this, 'deep', true);
82
+ });
83
+
84
+ /**
85
+ * ### .a(type)
86
+ *
87
+ * The `a` and `an` assertions are aliases that can be
88
+ * used either as language chains or to assert a value's
89
+ * type.
90
+ *
91
+ * // typeof
92
+ * expect('test').to.be.a('string');
93
+ * expect({ foo: 'bar' }).to.be.an('object');
94
+ * expect(null).to.be.a('null');
95
+ * expect(undefined).to.be.an('undefined');
96
+ *
97
+ * // language chain
98
+ * expect(foo).to.be.an.instanceof(Foo);
99
+ *
100
+ * @name a
101
+ * @alias an
102
+ * @param {String} type
103
+ * @param {String} message _optional_
104
+ * @api public
105
+ */
106
+
107
+ function an (type, msg) {
108
+ if (msg) flag(this, 'message', msg);
109
+ type = type.toLowerCase();
110
+ var obj = flag(this, 'object')
111
+ , article = ~[ 'a', 'e', 'i', 'o', 'u' ].indexOf(type.charAt(0)) ? 'an ' : 'a ';
112
+
113
+ this.assert(
114
+ type === _.type(obj)
115
+ , 'expected #{this} to be ' + article + type
116
+ , 'expected #{this} not to be ' + article + type
117
+ );
118
+ }
119
+
120
+ Assertion.addChainableMethod('an', an);
121
+ Assertion.addChainableMethod('a', an);
122
+
123
+ /**
124
+ * ### .include(value)
125
+ *
126
+ * The `include` and `contain` assertions can be used as either property
127
+ * based language chains or as methods to assert the inclusion of an object
128
+ * in an array or a substring in a string. When used as language chains,
129
+ * they toggle the `contain` flag for the `keys` assertion.
130
+ *
131
+ * expect([1,2,3]).to.include(2);
132
+ * expect('foobar').to.contain('foo');
133
+ * expect({ foo: 'bar', hello: 'universe' }).to.include.keys('foo');
134
+ *
135
+ * @name include
136
+ * @alias contain
137
+ * @param {Object|String|Number} obj
138
+ * @param {String} message _optional_
139
+ * @api public
140
+ */
141
+
142
+ function includeChainingBehavior () {
143
+ flag(this, 'contains', true);
144
+ }
145
+
146
+ function include (val, msg) {
147
+ if (msg) flag(this, 'message', msg);
148
+ var obj = flag(this, 'object')
149
+ this.assert(
150
+ ~obj.indexOf(val)
151
+ , 'expected #{this} to include ' + _.inspect(val)
152
+ , 'expected #{this} to not include ' + _.inspect(val));
153
+ }
154
+
155
+ Assertion.addChainableMethod('include', include, includeChainingBehavior);
156
+ Assertion.addChainableMethod('contain', include, includeChainingBehavior);
157
+
158
+ /**
159
+ * ### .ok
160
+ *
161
+ * Asserts that the target is truthy.
162
+ *
163
+ * expect('everthing').to.be.ok;
164
+ * expect(1).to.be.ok;
165
+ * expect(false).to.not.be.ok;
166
+ * expect(undefined).to.not.be.ok;
167
+ * expect(null).to.not.be.ok;
168
+ *
169
+ * @name ok
170
+ * @api public
171
+ */
172
+
173
+ Assertion.addProperty('ok', function () {
174
+ this.assert(
175
+ flag(this, 'object')
176
+ , 'expected #{this} to be truthy'
177
+ , 'expected #{this} to be falsy');
178
+ });
179
+
180
+ /**
181
+ * ### .true
182
+ *
183
+ * Asserts that the target is `true`.
184
+ *
185
+ * expect(true).to.be.true;
186
+ * expect(1).to.not.be.true;
187
+ *
188
+ * @name true
189
+ * @api public
190
+ */
191
+
192
+ Assertion.addProperty('true', function () {
193
+ this.assert(
194
+ true === flag(this, 'object')
195
+ , 'expected #{this} to be true'
196
+ , 'expected #{this} to be false'
197
+ , this.negate ? false : true
198
+ );
199
+ });
200
+
201
+ /**
202
+ * ### .false
203
+ *
204
+ * Asserts that the target is `false`.
205
+ *
206
+ * expect(false).to.be.false;
207
+ * expect(0).to.not.be.false;
208
+ *
209
+ * @name false
210
+ * @api public
211
+ */
212
+
213
+ Assertion.addProperty('false', function () {
214
+ this.assert(
215
+ false === flag(this, 'object')
216
+ , 'expected #{this} to be false'
217
+ , 'expected #{this} to be true'
218
+ , this.negate ? true : false
219
+ );
220
+ });
221
+
222
+ /**
223
+ * ### .null
224
+ *
225
+ * Asserts that the target is `null`.
226
+ *
227
+ * expect(null).to.be.null;
228
+ * expect(undefined).not.to.be.null;
229
+ *
230
+ * @name null
231
+ * @api public
232
+ */
233
+
234
+ Assertion.addProperty('null', function () {
235
+ this.assert(
236
+ null === flag(this, 'object')
237
+ , 'expected #{this} to be null'
238
+ , 'expected #{this} not to be null'
239
+ );
240
+ });
241
+
242
+ /**
243
+ * ### .undefined
244
+ *
245
+ * Asserts that the target is `undefined`.
246
+ *
247
+ * expect(undefined).to.be.undefined;
248
+ * expect(null).to.not.be.undefined;
249
+ *
250
+ * @name undefined
251
+ * @api public
252
+ */
253
+
254
+ Assertion.addProperty('undefined', function () {
255
+ this.assert(
256
+ undefined === flag(this, 'object')
257
+ , 'expected #{this} to be undefined'
258
+ , 'expected #{this} not to be undefined'
259
+ );
260
+ });
261
+
262
+ /**
263
+ * ### .exist
264
+ *
265
+ * Asserts that the target is neither `null` nor `undefined`.
266
+ *
267
+ * var foo = 'hi'
268
+ * , bar = null
269
+ * , baz;
270
+ *
271
+ * expect(foo).to.exist;
272
+ * expect(bar).to.not.exist;
273
+ * expect(baz).to.not.exist;
274
+ *
275
+ * @name exist
276
+ * @api public
277
+ */
278
+
279
+ Assertion.addProperty('exist', function () {
280
+ this.assert(
281
+ null != flag(this, 'object')
282
+ , 'expected #{this} to exist'
283
+ , 'expected #{this} to not exist'
284
+ );
285
+ });
286
+
287
+
288
+ /**
289
+ * ### .empty
290
+ *
291
+ * Asserts that the target's length is `0`. For arrays, it checks
292
+ * the `length` property. For objects, it gets the count of
293
+ * enumerable keys.
294
+ *
295
+ * expect([]).to.be.empty;
296
+ * expect('').to.be.empty;
297
+ * expect({}).to.be.empty;
298
+ *
299
+ * @name empty
300
+ * @api public
301
+ */
302
+
303
+ Assertion.addProperty('empty', function () {
304
+ var obj = flag(this, 'object')
305
+ , expected = obj;
306
+
307
+ if (Array.isArray(obj) || 'string' === typeof object) {
308
+ expected = obj.length;
309
+ } else if (typeof obj === 'object') {
310
+ expected = Object.keys(obj).length;
311
+ }
312
+
313
+ this.assert(
314
+ !expected
315
+ , 'expected #{this} to be empty'
316
+ , 'expected #{this} not to be empty'
317
+ );
318
+ });
319
+
320
+ /**
321
+ * ### .arguments
322
+ *
323
+ * Asserts that the target is an arguments object.
324
+ *
325
+ * function test () {
326
+ * expect(arguments).to.be.arguments;
327
+ * }
328
+ *
329
+ * @name arguments
330
+ * @alias Arguments
331
+ * @api public
332
+ */
333
+
334
+ function checkArguments () {
335
+ var obj = flag(this, 'object')
336
+ , type = Object.prototype.toString.call(obj);
337
+ this.assert(
338
+ '[object Arguments]' === type
339
+ , 'expected #{this} to be arguments but got ' + type
340
+ , 'expected #{this} to not be arguments'
341
+ );
342
+ }
343
+
344
+ Assertion.addProperty('arguments', checkArguments);
345
+ Assertion.addProperty('Arguments', checkArguments);
346
+
347
+ /**
348
+ * ### .equal(value)
349
+ *
350
+ * Asserts that the target is strictly equal (`===`) to `value`.
351
+ * Alternately, if the `deep` flag is set, asserts that
352
+ * the target is deeply equal to `value`.
353
+ *
354
+ * expect('hello').to.equal('hello');
355
+ * expect(42).to.equal(42);
356
+ * expect(1).to.not.equal(true);
357
+ * expect({ foo: 'bar' }).to.not.equal({ foo: 'bar' });
358
+ * expect({ foo: 'bar' }).to.deep.equal({ foo: 'bar' });
359
+ *
360
+ * @name equal
361
+ * @alias equals
362
+ * @alias eq
363
+ * @alias deep.equal
364
+ * @param {Mixed} value
365
+ * @param {String} message _optional_
366
+ * @api public
367
+ */
368
+
369
+ function assertEqual (val, msg) {
370
+ if (msg) flag(this, 'message', msg);
371
+ var obj = flag(this, 'object');
372
+ if (flag(this, 'deep')) {
373
+ return this.eql(val);
374
+ } else {
375
+ this.assert(
376
+ val === obj
377
+ , 'expected #{this} to equal #{exp}'
378
+ , 'expected #{this} to not equal #{exp}'
379
+ , val
380
+ , this._obj
381
+ , true
382
+ );
383
+ }
384
+ }
385
+
386
+ Assertion.addMethod('equal', assertEqual);
387
+ Assertion.addMethod('equals', assertEqual);
388
+ Assertion.addMethod('eq', assertEqual);
389
+
390
+ /**
391
+ * ### .eql(value)
392
+ *
393
+ * Asserts that the target is deeply equal to `value`.
394
+ *
395
+ * expect({ foo: 'bar' }).to.eql({ foo: 'bar' });
396
+ * expect([ 1, 2, 3 ]).to.eql([ 1, 2, 3 ]);
397
+ *
398
+ * @name eql
399
+ * @alias eqls
400
+ * @param {Mixed} value
401
+ * @param {String} message _optional_
402
+ * @api public
403
+ */
404
+
405
+ function assertEql(obj, msg) {
406
+ if (msg) flag(this, 'message', msg);
407
+ this.assert(
408
+ _.eql(obj, flag(this, 'object'))
409
+ , 'expected #{this} to deeply equal #{exp}'
410
+ , 'expected #{this} to not deeply equal #{exp}'
411
+ , obj
412
+ , this._obj
413
+ , true
414
+ );
415
+ }
416
+
417
+ Assertion.addMethod('eql', assertEql);
418
+ Assertion.addMethod('eqls', assertEql);
419
+
420
+ /**
421
+ * ### .above(value)
422
+ *
423
+ * Asserts that the target is greater than `value`.
424
+ *
425
+ * expect(10).to.be.above(5);
426
+ *
427
+ * Can also be used in conjunction with `length` to
428
+ * assert a minimum length. The benefit being a
429
+ * more informative error message than if the length
430
+ * was supplied directly.
431
+ *
432
+ * expect('foo').to.have.length.above(2);
433
+ * expect([ 1, 2, 3 ]).to.have.length.above(2);
434
+ *
435
+ * @name above
436
+ * @alias gt
437
+ * @alias greaterThan
438
+ * @param {Number} value
439
+ * @param {String} message _optional_
440
+ * @api public
441
+ */
442
+
443
+ function assertAbove (n, msg) {
444
+ if (msg) flag(this, 'message', msg);
445
+ var obj = flag(this, 'object');
446
+ if (flag(this, 'doLength')) {
447
+ new Assertion(obj, msg).to.have.property('length');
448
+ var len = obj.length;
449
+ this.assert(
450
+ len > n
451
+ , 'expected #{this} to have a length above #{exp} but got #{act}'
452
+ , 'expected #{this} to not have a length above #{exp}'
453
+ , n
454
+ , len
455
+ );
456
+ } else {
457
+ this.assert(
458
+ obj > n
459
+ , 'expected #{this} to be above ' + n
460
+ , 'expected #{this} to be at most ' + n
461
+ );
462
+ }
463
+ }
464
+
465
+ Assertion.addMethod('above', assertAbove);
466
+ Assertion.addMethod('gt', assertAbove);
467
+ Assertion.addMethod('greaterThan', assertAbove);
468
+
469
+ /**
470
+ * ### .least(value)
471
+ *
472
+ * Asserts that the target is greater than or equal to `value`.
473
+ *
474
+ * expect(10).to.be.at.least(10);
475
+ *
476
+ * Can also be used in conjunction with `length` to
477
+ * assert a minimum length. The benefit being a
478
+ * more informative error message than if the length
479
+ * was supplied directly.
480
+ *
481
+ * expect('foo').to.have.length.of.at.least(2);
482
+ * expect([ 1, 2, 3 ]).to.have.length.of.at.least(3);
483
+ *
484
+ * @name least
485
+ * @alias gte
486
+ * @param {Number} value
487
+ * @param {String} message _optional_
488
+ * @api public
489
+ */
490
+
491
+ function assertLeast (n, msg) {
492
+ if (msg) flag(this, 'message', msg);
493
+ var obj = flag(this, 'object');
494
+ if (flag(this, 'doLength')) {
495
+ new Assertion(obj, msg).to.have.property('length');
496
+ var len = obj.length;
497
+ this.assert(
498
+ len >= n
499
+ , 'expected #{this} to have a length at least #{exp} but got #{act}'
500
+ , 'expected #{this} to have a length below #{exp}'
501
+ , n
502
+ , len
503
+ );
504
+ } else {
505
+ this.assert(
506
+ obj >= n
507
+ , 'expected #{this} to be at least ' + n
508
+ , 'expected #{this} to be below ' + n
509
+ );
510
+ }
511
+ }
512
+
513
+ Assertion.addMethod('least', assertLeast);
514
+ Assertion.addMethod('gte', assertLeast);
515
+
516
+ /**
517
+ * ### .below(value)
518
+ *
519
+ * Asserts that the target is less than `value`.
520
+ *
521
+ * expect(5).to.be.below(10);
522
+ *
523
+ * Can also be used in conjunction with `length` to
524
+ * assert a maximum length. The benefit being a
525
+ * more informative error message than if the length
526
+ * was supplied directly.
527
+ *
528
+ * expect('foo').to.have.length.below(4);
529
+ * expect([ 1, 2, 3 ]).to.have.length.below(4);
530
+ *
531
+ * @name below
532
+ * @alias lt
533
+ * @alias lessThan
534
+ * @param {Number} value
535
+ * @param {String} message _optional_
536
+ * @api public
537
+ */
538
+
539
+ function assertBelow (n, msg) {
540
+ if (msg) flag(this, 'message', msg);
541
+ var obj = flag(this, 'object');
542
+ if (flag(this, 'doLength')) {
543
+ new Assertion(obj, msg).to.have.property('length');
544
+ var len = obj.length;
545
+ this.assert(
546
+ len < n
547
+ , 'expected #{this} to have a length below #{exp} but got #{act}'
548
+ , 'expected #{this} to not have a length below #{exp}'
549
+ , n
550
+ , len
551
+ );
552
+ } else {
553
+ this.assert(
554
+ obj < n
555
+ , 'expected #{this} to be below ' + n
556
+ , 'expected #{this} to be at least ' + n
557
+ );
558
+ }
559
+ }
560
+
561
+ Assertion.addMethod('below', assertBelow);
562
+ Assertion.addMethod('lt', assertBelow);
563
+ Assertion.addMethod('lessThan', assertBelow);
564
+
565
+ /**
566
+ * ### .most(value)
567
+ *
568
+ * Asserts that the target is less than or equal to `value`.
569
+ *
570
+ * expect(5).to.be.at.most(5);
571
+ *
572
+ * Can also be used in conjunction with `length` to
573
+ * assert a maximum length. The benefit being a
574
+ * more informative error message than if the length
575
+ * was supplied directly.
576
+ *
577
+ * expect('foo').to.have.length.of.at.most(4);
578
+ * expect([ 1, 2, 3 ]).to.have.length.of.at.most(3);
579
+ *
580
+ * @name most
581
+ * @alias lte
582
+ * @param {Number} value
583
+ * @param {String} message _optional_
584
+ * @api public
585
+ */
586
+
587
+ function assertMost (n, msg) {
588
+ if (msg) flag(this, 'message', msg);
589
+ var obj = flag(this, 'object');
590
+ if (flag(this, 'doLength')) {
591
+ new Assertion(obj, msg).to.have.property('length');
592
+ var len = obj.length;
593
+ this.assert(
594
+ len <= n
595
+ , 'expected #{this} to have a length at most #{exp} but got #{act}'
596
+ , 'expected #{this} to have a length above #{exp}'
597
+ , n
598
+ , len
599
+ );
600
+ } else {
601
+ this.assert(
602
+ obj <= n
603
+ , 'expected #{this} to be at most ' + n
604
+ , 'expected #{this} to be above ' + n
605
+ );
606
+ }
607
+ }
608
+
609
+ Assertion.addMethod('most', assertMost);
610
+ Assertion.addMethod('lte', assertMost);
611
+
612
+ /**
613
+ * ### .within(start, finish)
614
+ *
615
+ * Asserts that the target is within a range.
616
+ *
617
+ * expect(7).to.be.within(5,10);
618
+ *
619
+ * Can also be used in conjunction with `length` to
620
+ * assert a length range. The benefit being a
621
+ * more informative error message than if the length
622
+ * was supplied directly.
623
+ *
624
+ * expect('foo').to.have.length.within(2,4);
625
+ * expect([ 1, 2, 3 ]).to.have.length.within(2,4);
626
+ *
627
+ * @name within
628
+ * @param {Number} start lowerbound inclusive
629
+ * @param {Number} finish upperbound inclusive
630
+ * @param {String} message _optional_
631
+ * @api public
632
+ */
633
+
634
+ Assertion.addMethod('within', function (start, finish, msg) {
635
+ if (msg) flag(this, 'message', msg);
636
+ var obj = flag(this, 'object')
637
+ , range = start + '..' + finish;
638
+ if (flag(this, 'doLength')) {
639
+ new Assertion(obj, msg).to.have.property('length');
640
+ var len = obj.length;
641
+ this.assert(
642
+ len >= start && len <= finish
643
+ , 'expected #{this} to have a length within ' + range
644
+ , 'expected #{this} to not have a length within ' + range
645
+ );
646
+ } else {
647
+ this.assert(
648
+ obj >= start && obj <= finish
649
+ , 'expected #{this} to be within ' + range
650
+ , 'expected #{this} to not be within ' + range
651
+ );
652
+ }
653
+ });
654
+
655
+ /**
656
+ * ### .instanceof(constructor)
657
+ *
658
+ * Asserts that the target is an instance of `constructor`.
659
+ *
660
+ * var Tea = function (name) { this.name = name; }
661
+ * , Chai = new Tea('chai');
662
+ *
663
+ * expect(Chai).to.be.an.instanceof(Tea);
664
+ * expect([ 1, 2, 3 ]).to.be.instanceof(Array);
665
+ *
666
+ * @name instanceof
667
+ * @param {Constructor} constructor
668
+ * @param {String} message _optional_
669
+ * @alias instanceOf
670
+ * @api public
671
+ */
672
+
673
+ function assertInstanceOf (constructor, msg) {
674
+ if (msg) flag(this, 'message', msg);
675
+ var name = _.getName(constructor);
676
+ this.assert(
677
+ flag(this, 'object') instanceof constructor
678
+ , 'expected #{this} to be an instance of ' + name
679
+ , 'expected #{this} to not be an instance of ' + name
680
+ );
681
+ };
682
+
683
+ Assertion.addMethod('instanceof', assertInstanceOf);
684
+ Assertion.addMethod('instanceOf', assertInstanceOf);
685
+
686
+ /**
687
+ * ### .property(name, [value])
688
+ *
689
+ * Asserts that the target has a property `name`, optionally asserting that
690
+ * the value of that property is strictly equal to `value`.
691
+ * If the `deep` flag is set, you can use dot- and bracket-notation for deep
692
+ * references into objects and arrays.
693
+ *
694
+ * // simple referencing
695
+ * var obj = { foo: 'bar' };
696
+ * expect(obj).to.have.property('foo');
697
+ * expect(obj).to.have.property('foo', 'bar');
698
+ *
699
+ * // deep referencing
700
+ * var deepObj = {
701
+ * green: { tea: 'matcha' }
702
+ * , teas: [ 'chai', 'matcha', { tea: 'konacha' } ]
703
+ * };
704
+
705
+ * expect(deepObj).to.have.deep.property('green.tea', 'matcha');
706
+ * expect(deepObj).to.have.deep.property('teas[1]', 'matcha');
707
+ * expect(deepObj).to.have.deep.property('teas[2].tea', 'konacha');
708
+ *
709
+ * You can also use an array as the starting point of a `deep.property`
710
+ * assertion, or traverse nested arrays.
711
+ *
712
+ * var arr = [
713
+ * [ 'chai', 'matcha', 'konacha' ]
714
+ * , [ { tea: 'chai' }
715
+ * , { tea: 'matcha' }
716
+ * , { tea: 'konacha' } ]
717
+ * ];
718
+ *
719
+ * expect(arr).to.have.deep.property('[0][1]', 'matcha');
720
+ * expect(arr).to.have.deep.property('[1][2].tea', 'konacha');
721
+ *
722
+ * Furthermore, `property` changes the subject of the assertion
723
+ * to be the value of that property from the original object. This
724
+ * permits for further chainable assertions on that property.
725
+ *
726
+ * expect(obj).to.have.property('foo')
727
+ * .that.is.a('string');
728
+ * expect(deepObj).to.have.property('green')
729
+ * .that.is.an('object')
730
+ * .that.deep.equals({ tea: 'matcha' });
731
+ * expect(deepObj).to.have.property('teas')
732
+ * .that.is.an('array')
733
+ * .with.deep.property('[2]')
734
+ * .that.deep.equals({ tea: 'konacha' });
735
+ *
736
+ * @name property
737
+ * @alias deep.property
738
+ * @param {String} name
739
+ * @param {Mixed} value (optional)
740
+ * @param {String} message _optional_
741
+ * @returns value of property for chaining
742
+ * @api public
743
+ */
744
+
745
+ Assertion.addMethod('property', function (name, val, msg) {
746
+ if (msg) flag(this, 'message', msg);
747
+
748
+ var descriptor = flag(this, 'deep') ? 'deep property ' : 'property '
749
+ , negate = flag(this, 'negate')
750
+ , obj = flag(this, 'object')
751
+ , value = flag(this, 'deep')
752
+ ? _.getPathValue(name, obj)
753
+ : obj[name];
754
+
755
+ if (negate && undefined !== val) {
756
+ if (undefined === value) {
757
+ msg = (msg != null) ? msg + ': ' : '';
758
+ throw new Error(msg + _.inspect(obj) + ' has no ' + descriptor + _.inspect(name));
759
+ }
760
+ } else {
761
+ this.assert(
762
+ undefined !== value
763
+ , 'expected #{this} to have a ' + descriptor + _.inspect(name)
764
+ , 'expected #{this} to not have ' + descriptor + _.inspect(name));
765
+ }
766
+
767
+ if (undefined !== val) {
768
+ this.assert(
769
+ val === value
770
+ , 'expected #{this} to have a ' + descriptor + _.inspect(name) + ' of #{exp}, but got #{act}'
771
+ , 'expected #{this} to not have a ' + descriptor + _.inspect(name) + ' of #{act}'
772
+ , val
773
+ , value
774
+ );
775
+ }
776
+
777
+ flag(this, 'object', value);
778
+ });
779
+
780
+
781
+ /**
782
+ * ### .ownProperty(name)
783
+ *
784
+ * Asserts that the target has an own property `name`.
785
+ *
786
+ * expect('test').to.have.ownProperty('length');
787
+ *
788
+ * @name ownProperty
789
+ * @alias haveOwnProperty
790
+ * @param {String} name
791
+ * @param {String} message _optional_
792
+ * @api public
793
+ */
794
+
795
+ function assertOwnProperty (name, msg) {
796
+ if (msg) flag(this, 'message', msg);
797
+ var obj = flag(this, 'object');
798
+ this.assert(
799
+ obj.hasOwnProperty(name)
800
+ , 'expected #{this} to have own property ' + _.inspect(name)
801
+ , 'expected #{this} to not have own property ' + _.inspect(name)
802
+ );
803
+ }
804
+
805
+ Assertion.addMethod('ownProperty', assertOwnProperty);
806
+ Assertion.addMethod('haveOwnProperty', assertOwnProperty);
807
+
808
+ /**
809
+ * ### .length(value)
810
+ *
811
+ * Asserts that the target's `length` property has
812
+ * the expected value.
813
+ *
814
+ * expect([ 1, 2, 3]).to.have.length(3);
815
+ * expect('foobar').to.have.length(6);
816
+ *
817
+ * Can also be used as a chain precursor to a value
818
+ * comparison for the length property.
819
+ *
820
+ * expect('foo').to.have.length.above(2);
821
+ * expect([ 1, 2, 3 ]).to.have.length.above(2);
822
+ * expect('foo').to.have.length.below(4);
823
+ * expect([ 1, 2, 3 ]).to.have.length.below(4);
824
+ * expect('foo').to.have.length.within(2,4);
825
+ * expect([ 1, 2, 3 ]).to.have.length.within(2,4);
826
+ *
827
+ * @name length
828
+ * @alias lengthOf
829
+ * @param {Number} length
830
+ * @param {String} message _optional_
831
+ * @api public
832
+ */
833
+
834
+ function assertLengthChain () {
835
+ flag(this, 'doLength', true);
836
+ }
837
+
838
+ function assertLength (n, msg) {
839
+ if (msg) flag(this, 'message', msg);
840
+ var obj = flag(this, 'object');
841
+ new Assertion(obj, msg).to.have.property('length');
842
+ var len = obj.length;
843
+
844
+ this.assert(
845
+ len == n
846
+ , 'expected #{this} to have a length of #{exp} but got #{act}'
847
+ , 'expected #{this} to not have a length of #{act}'
848
+ , n
849
+ , len
850
+ );
851
+ }
852
+
853
+ Assertion.addChainableMethod('length', assertLength, assertLengthChain);
854
+ Assertion.addMethod('lengthOf', assertLength, assertLengthChain);
855
+
856
+ /**
857
+ * ### .match(regexp)
858
+ *
859
+ * Asserts that the target matches a regular expression.
860
+ *
861
+ * expect('foobar').to.match(/^foo/);
862
+ *
863
+ * @name match
864
+ * @param {RegExp} RegularExpression
865
+ * @param {String} message _optional_
866
+ * @api public
867
+ */
868
+
869
+ Assertion.addMethod('match', function (re, msg) {
870
+ if (msg) flag(this, 'message', msg);
871
+ var obj = flag(this, 'object');
872
+ this.assert(
873
+ re.exec(obj)
874
+ , 'expected #{this} to match ' + re
875
+ , 'expected #{this} not to match ' + re
876
+ );
877
+ });
878
+
879
+ /**
880
+ * ### .string(string)
881
+ *
882
+ * Asserts that the string target contains another string.
883
+ *
884
+ * expect('foobar').to.have.string('bar');
885
+ *
886
+ * @name string
887
+ * @param {String} string
888
+ * @param {String} message _optional_
889
+ * @api public
890
+ */
891
+
892
+ Assertion.addMethod('string', function (str, msg) {
893
+ if (msg) flag(this, 'message', msg);
894
+ var obj = flag(this, 'object');
895
+ new Assertion(obj, msg).is.a('string');
896
+
897
+ this.assert(
898
+ ~obj.indexOf(str)
899
+ , 'expected #{this} to contain ' + _.inspect(str)
900
+ , 'expected #{this} to not contain ' + _.inspect(str)
901
+ );
902
+ });
903
+
904
+
905
+ /**
906
+ * ### .keys(key1, [key2], [...])
907
+ *
908
+ * Asserts that the target has exactly the given keys, or
909
+ * asserts the inclusion of some keys when using the
910
+ * `include` or `contain` modifiers.
911
+ *
912
+ * expect({ foo: 1, bar: 2 }).to.have.keys(['foo', 'bar']);
913
+ * expect({ foo: 1, bar: 2, baz: 3 }).to.contain.keys('foo', 'bar');
914
+ *
915
+ * @name keys
916
+ * @alias key
917
+ * @param {String...|Array} keys
918
+ * @api public
919
+ */
920
+
921
+ function assertKeys (keys) {
922
+ var obj = flag(this, 'object')
923
+ , str
924
+ , ok = true;
925
+
926
+ keys = keys instanceof Array
927
+ ? keys
928
+ : Array.prototype.slice.call(arguments);
929
+
930
+ if (!keys.length) throw new Error('keys required');
931
+
932
+ var actual = Object.keys(obj)
933
+ , len = keys.length;
934
+
935
+ // Inclusion
936
+ ok = keys.every(function(key){
937
+ return ~actual.indexOf(key);
938
+ });
939
+
940
+ // Strict
941
+ if (!flag(this, 'negate') && !flag(this, 'contains')) {
942
+ ok = ok && keys.length == actual.length;
943
+ }
944
+
945
+ // Key string
946
+ if (len > 1) {
947
+ keys = keys.map(function(key){
948
+ return _.inspect(key);
949
+ });
950
+ var last = keys.pop();
951
+ str = keys.join(', ') + ', and ' + last;
952
+ } else {
953
+ str = _.inspect(keys[0]);
954
+ }
955
+
956
+ // Form
957
+ str = (len > 1 ? 'keys ' : 'key ') + str;
958
+
959
+ // Have / include
960
+ str = (flag(this, 'contains') ? 'contain ' : 'have ') + str;
961
+
962
+ // Assertion
963
+ this.assert(
964
+ ok
965
+ , 'expected #{this} to ' + str
966
+ , 'expected #{this} to not ' + str
967
+ );
968
+ }
969
+
970
+ Assertion.addMethod('keys', assertKeys);
971
+ Assertion.addMethod('key', assertKeys);
972
+
973
+ /**
974
+ * ### .throw(constructor)
975
+ *
976
+ * Asserts that the function target will throw a specific error, or specific type of error
977
+ * (as determined using `instanceof`), optionally with a RegExp or string inclusion test
978
+ * for the error's message.
979
+ *
980
+ * var err = new ReferenceError('This is a bad function.');
981
+ * var fn = function () { throw err; }
982
+ * expect(fn).to.throw(ReferenceError);
983
+ * expect(fn).to.throw(Error);
984
+ * expect(fn).to.throw(/bad function/);
985
+ * expect(fn).to.not.throw('good function');
986
+ * expect(fn).to.throw(ReferenceError, /bad function/);
987
+ * expect(fn).to.throw(err);
988
+ * expect(fn).to.not.throw(new RangeError('Out of range.'));
989
+ *
990
+ * Please note that when a throw expectation is negated, it will check each
991
+ * parameter independently, starting with error constructor type. The appropriate way
992
+ * to check for the existence of a type of error but for a message that does not match
993
+ * is to use `and`.
994
+ *
995
+ * expect(fn).to.throw(ReferenceError)
996
+ * .and.not.throw(/good function/);
997
+ *
998
+ * @name throw
999
+ * @alias throws
1000
+ * @alias Throw
1001
+ * @param {ErrorConstructor} constructor
1002
+ * @param {String|RegExp} expected error message
1003
+ * @param {String} message _optional_
1004
+ * @see https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Error#Error_types
1005
+ * @api public
1006
+ */
1007
+
1008
+ function assertThrows (constructor, errMsg, msg) {
1009
+ if (msg) flag(this, 'message', msg);
1010
+ var obj = flag(this, 'object');
1011
+ new Assertion(obj, msg).is.a('function');
1012
+
1013
+ var thrown = false
1014
+ , desiredError = null
1015
+ , name = null
1016
+ , thrownError = null;
1017
+
1018
+ if (arguments.length === 0) {
1019
+ errMsg = null;
1020
+ constructor = null;
1021
+ } else if (constructor && (constructor instanceof RegExp || 'string' === typeof constructor)) {
1022
+ errMsg = constructor;
1023
+ constructor = null;
1024
+ } else if (constructor && constructor instanceof Error) {
1025
+ desiredError = constructor;
1026
+ constructor = null;
1027
+ errMsg = null;
1028
+ } else if (typeof constructor === 'function') {
1029
+ name = (new constructor()).name;
1030
+ } else {
1031
+ constructor = null;
1032
+ }
1033
+
1034
+ try {
1035
+ obj();
1036
+ } catch (err) {
1037
+ // first, check desired error
1038
+ if (desiredError) {
1039
+ this.assert(
1040
+ err === desiredError
1041
+ , 'expected #{this} to throw #{exp} but #{act} was thrown'
1042
+ , 'expected #{this} to not throw #{exp}'
1043
+ , desiredError
1044
+ , err
1045
+ );
1046
+
1047
+ return this;
1048
+ }
1049
+ // next, check constructor
1050
+ if (constructor) {
1051
+ this.assert(
1052
+ err instanceof constructor
1053
+ , 'expected #{this} to throw #{exp} but #{act} was thrown'
1054
+ , 'expected #{this} to not throw #{exp} but #{act} was thrown'
1055
+ , name
1056
+ , err
1057
+ );
1058
+
1059
+ if (!errMsg) return this;
1060
+ }
1061
+ // next, check message
1062
+ var message = 'object' === _.type(err) && "message" in err
1063
+ ? err.message
1064
+ : '' + err;
1065
+
1066
+ if ((message != null) && errMsg && errMsg instanceof RegExp) {
1067
+ this.assert(
1068
+ errMsg.exec(message)
1069
+ , 'expected #{this} to throw error matching #{exp} but got #{act}'
1070
+ , 'expected #{this} to throw error not matching #{exp}'
1071
+ , errMsg
1072
+ , message
1073
+ );
1074
+
1075
+ return this;
1076
+ } else if ((message != null) && errMsg && 'string' === typeof errMsg) {
1077
+ this.assert(
1078
+ ~message.indexOf(errMsg)
1079
+ , 'expected #{this} to throw error including #{exp} but got #{act}'
1080
+ , 'expected #{this} to throw error not including #{act}'
1081
+ , errMsg
1082
+ , message
1083
+ );
1084
+
1085
+ return this;
1086
+ } else {
1087
+ thrown = true;
1088
+ thrownError = err;
1089
+ }
1090
+ }
1091
+
1092
+ var actuallyGot = ''
1093
+ , expectedThrown = name !== null
1094
+ ? name
1095
+ : desiredError
1096
+ ? '#{exp}' //_.inspect(desiredError)
1097
+ : 'an error';
1098
+
1099
+ if (thrown) {
1100
+ actuallyGot = ' but #{act} was thrown'
1101
+ }
1102
+
1103
+ this.assert(
1104
+ thrown === true
1105
+ , 'expected #{this} to throw ' + expectedThrown + actuallyGot
1106
+ , 'expected #{this} to not throw ' + expectedThrown + actuallyGot
1107
+ , desiredError
1108
+ , thrownError
1109
+ );
1110
+ };
1111
+
1112
+ Assertion.addMethod('throw', assertThrows);
1113
+ Assertion.addMethod('throws', assertThrows);
1114
+ Assertion.addMethod('Throw', assertThrows);
1115
+
1116
+ /**
1117
+ * ### .respondTo(method)
1118
+ *
1119
+ * Asserts that the object or class target will respond to a method.
1120
+ *
1121
+ * Klass.prototype.bar = function(){};
1122
+ * expect(Klass).to.respondTo('bar');
1123
+ * expect(obj).to.respondTo('bar');
1124
+ *
1125
+ * To check if a constructor will respond to a static function,
1126
+ * set the `itself` flag.
1127
+ *
1128
+ * Klass.baz = function(){};
1129
+ * expect(Klass).itself.to.respondTo('baz');
1130
+ *
1131
+ * @name respondTo
1132
+ * @param {String} method
1133
+ * @param {String} message _optional_
1134
+ * @api public
1135
+ */
1136
+
1137
+ Assertion.addMethod('respondTo', function (method, msg) {
1138
+ if (msg) flag(this, 'message', msg);
1139
+ var obj = flag(this, 'object')
1140
+ , itself = flag(this, 'itself')
1141
+ , context = ('function' === _.type(obj) && !itself)
1142
+ ? obj.prototype[method]
1143
+ : obj[method];
1144
+
1145
+ this.assert(
1146
+ 'function' === typeof context
1147
+ , 'expected #{this} to respond to ' + _.inspect(method)
1148
+ , 'expected #{this} to not respond to ' + _.inspect(method)
1149
+ );
1150
+ });
1151
+
1152
+ /**
1153
+ * ### .itself
1154
+ *
1155
+ * Sets the `itself` flag, later used by the `respondTo` assertion.
1156
+ *
1157
+ * function Foo() {}
1158
+ * Foo.bar = function() {}
1159
+ * Foo.prototype.baz = function() {}
1160
+ *
1161
+ * expect(Foo).itself.to.respondTo('bar');
1162
+ * expect(Foo).itself.not.to.respondTo('baz');
1163
+ *
1164
+ * @name itself
1165
+ * @api public
1166
+ */
1167
+
1168
+ Assertion.addProperty('itself', function () {
1169
+ flag(this, 'itself', true);
1170
+ });
1171
+
1172
+ /**
1173
+ * ### .satisfy(method)
1174
+ *
1175
+ * Asserts that the target passes a given truth test.
1176
+ *
1177
+ * expect(1).to.satisfy(function(num) { return num > 0; });
1178
+ *
1179
+ * @name satisfy
1180
+ * @param {Function} matcher
1181
+ * @param {String} message _optional_
1182
+ * @api public
1183
+ */
1184
+
1185
+ Assertion.addMethod('satisfy', function (matcher, msg) {
1186
+ if (msg) flag(this, 'message', msg);
1187
+ var obj = flag(this, 'object');
1188
+ this.assert(
1189
+ matcher(obj)
1190
+ , 'expected #{this} to satisfy ' + _.objDisplay(matcher)
1191
+ , 'expected #{this} to not satisfy' + _.objDisplay(matcher)
1192
+ , this.negate ? false : true
1193
+ , matcher(obj)
1194
+ );
1195
+ });
1196
+
1197
+ /**
1198
+ * ### .closeTo(expected, delta)
1199
+ *
1200
+ * Asserts that the target is equal `expected`, to within a +/- `delta` range.
1201
+ *
1202
+ * expect(1.5).to.be.closeTo(1, 0.5);
1203
+ *
1204
+ * @name closeTo
1205
+ * @param {Number} expected
1206
+ * @param {Number} delta
1207
+ * @param {String} message _optional_
1208
+ * @api public
1209
+ */
1210
+
1211
+ Assertion.addMethod('closeTo', function (expected, delta, msg) {
1212
+ if (msg) flag(this, 'message', msg);
1213
+ var obj = flag(this, 'object');
1214
+ this.assert(
1215
+ Math.abs(obj - expected) <= delta
1216
+ , 'expected #{this} to be close to ' + expected + ' +/- ' + delta
1217
+ , 'expected #{this} not to be close to ' + expected + ' +/- ' + delta
1218
+ );
1219
+ });
1220
+
1221
+ function isSubsetOf(subset, superset) {
1222
+ return subset.every(function(elem) {
1223
+ return superset.indexOf(elem) !== -1;
1224
+ })
1225
+ }
1226
+
1227
+ /**
1228
+ * ### .members
1229
+ *
1230
+ * Asserts that the target is a superset of `set`,
1231
+ * or that the target and `set` have the same members.
1232
+ *
1233
+ * expect([1, 2, 3]).to.include.members([3, 2]);
1234
+ * expect([1, 2, 3]).to.not.include.members([3, 2, 8]);
1235
+ *
1236
+ * expect([4, 2]).to.have.members([2, 4]);
1237
+ * expect([5, 2]).to.not.have.members([5, 2, 1]);
1238
+ *
1239
+ * @name members
1240
+ * @param {Array} set
1241
+ * @param {String} message _optional_
1242
+ * @api public
1243
+ */
1244
+
1245
+ Assertion.addMethod('members', function (subset, msg) {
1246
+ if (msg) flag(this, 'message', msg);
1247
+ var obj = flag(this, 'object');
1248
+
1249
+ new Assertion(obj).to.be.an('array');
1250
+ new Assertion(subset).to.be.an('array');
1251
+
1252
+ if (flag(this, 'contains')) {
1253
+ return this.assert(
1254
+ isSubsetOf(subset, obj)
1255
+ , 'expected #{this} to be a superset of #{act}'
1256
+ , 'expected #{this} to not be a superset of #{act}'
1257
+ , obj
1258
+ , subset
1259
+ );
1260
+ }
1261
+
1262
+ this.assert(
1263
+ isSubsetOf(obj, subset) && isSubsetOf(subset, obj)
1264
+ , 'expected #{this} to have the same members as #{act}'
1265
+ , 'expected #{this} to not have the same members as #{act}'
1266
+ , obj
1267
+ , subset
1268
+ );
1269
+ });
1270
+ };