Skip to content

Commit 77ca057

Browse files
committed
Implement iterable assertion
1 parent 44b81df commit 77ca057

File tree

5 files changed

+144
-11
lines changed

5 files changed

+144
-11
lines changed

lib/chai/core/assertions.js

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -319,6 +319,12 @@ function an (type, msg) {
319319
, 'expected #{this} to be ' + article + type
320320
, 'expected #{this} not to be ' + article + type
321321
);
322+
} else if (type === 'iterable') {
323+
this.assert(
324+
typeof obj !== 'string' && obj != undefined && obj[Symbol.iterator]
325+
, 'expected #{this} to be ' + article + type
326+
, 'expected #{this} not to be ' + article + type
327+
);
322328
} else {
323329
this.assert(
324330
type === detectedType
@@ -3133,7 +3139,6 @@ function isSubsetOf(subset, superset, cmp, contains, ordered) {
31333139
* @namespace BDD
31343140
* @api public
31353141
*/
3136-
31373142
Assertion.addMethod('members', function (subset, msg) {
31383143
if (msg) flag(this, 'message', msg);
31393144
var obj = flag(this, 'object')
@@ -3170,6 +3175,36 @@ Assertion.addMethod('members', function (subset, msg) {
31703175
);
31713176
});
31723177

3178+
/**
3179+
* ### .iterable
3180+
*
3181+
* Asserts that the target is an iterable, which means that it has a iterator
3182+
* with the exception of `String.`
3183+
*
3184+
* expect([1, 2]).to.be.iterable;
3185+
*
3186+
* Add `.not` earlier in the chain to negate `.iterable`.
3187+
*
3188+
* expect(1).to.not.be.iterable;
3189+
* expect("foobar").to.not.be.iterable;
3190+
*
3191+
* A custom error message can be given as the second argument to `expect`.
3192+
*
3193+
* expect(1, 'nooo why fail??').to.be.iterable;
3194+
*
3195+
* @name iterable
3196+
* @namespace BDD
3197+
* @api public
3198+
*/
3199+
Assertion.addProperty('iterable', function(msg) {
3200+
if (msg) flag(this, 'message', msg);
3201+
var obj = flag(this, 'object')
3202+
, flagMsg = flag(this, 'message')
3203+
, ssfi = flag(this, 'ssfi');
3204+
3205+
new Assertion(obj, flagMsg, ssfi, true).to.be.an('iterable');
3206+
});
3207+
31733208
/**
31743209
* ### .oneOf(list[, msg])
31753210
*

lib/chai/interface/assert.js

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ import * as chai from '../../../index.js';
88
import {Assertion} from '../assertion.js';
99
import {flag, inspect} from '../utils/index.js';
1010
import {AssertionError} from 'assertion-error';
11-
import {type} from '../utils/type-detect.js';
1211

1312
/**
1413
* ### assert(expression, message)
@@ -2485,6 +2484,23 @@ assert.oneOf = function (inList, list, msg) {
24852484
new Assertion(inList, msg, assert.oneOf, true).to.be.oneOf(list);
24862485
}
24872486

2487+
/**
2488+
* ### isIterable(obj, [message])
2489+
*
2490+
* Asserts that the target is an iterable, which means that it has a iterator
2491+
* with the exception of `String.`
2492+
*
2493+
* assert.isIterable([1, 2]);
2494+
*
2495+
* @param {unknown} obj
2496+
* @param {string} [msg]
2497+
* @namespace Assert
2498+
* @api public
2499+
*/
2500+
assert.isIterable = function(obj, msg) {
2501+
new Assertion(obj, msg, assert.isIterable, true).to.be.an('iterable');
2502+
}
2503+
24882504
/**
24892505
* ### .changes(function, object, property, [message])
24902506
*

test/assert.js

Lines changed: 32 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1979,11 +1979,11 @@ describe('assert', function () {
19791979

19801980
err(function () {
19811981
assert.sameMembers({}, [], 'blah');
1982-
}, 'blah: expected {} to be an array');
1982+
}, 'blah: expected {} to be an iterable');
19831983

19841984
err(function () {
19851985
assert.sameMembers([], {}, 'blah');
1986-
}, 'blah: expected {} to be an array');
1986+
}, 'blah: expected {} to be an iterable');
19871987
});
19881988

19891989
it('notSameMembers', function() {
@@ -2375,6 +2375,36 @@ describe('assert', function () {
23752375
}, 'blah: the argument to most must be a number');
23762376
});
23772377

2378+
it('iterable', function() {
2379+
assert.isIterable([1, 2, 3]);
2380+
assert.isIterable(new Map([[1, 'one'], [2, 'two'], [3, 'three']]));
2381+
assert.isIterable(new Set([1, 2, 3]));
2382+
2383+
err(function() {
2384+
assert.isIterable(42);
2385+
}, 'expected 42 to be an iterable');
2386+
2387+
err(function() {
2388+
assert.isIterable('hello');
2389+
}, "expected 'hello' to be an iterable");
2390+
2391+
err(function() {
2392+
assert.isIterable(undefined);
2393+
}, 'expected undefined to be an iterable');
2394+
2395+
err(function() {
2396+
assert.isIterable(null);
2397+
}, 'expected null to be an iterable');
2398+
2399+
err(function() {
2400+
assert.isIterable(true);
2401+
}, 'expected true to be an iterable');
2402+
2403+
err(function() {
2404+
assert.isIterable({ key: 'value' });
2405+
}, 'expected { key: \'value\' } to be an iterable');
2406+
});
2407+
23782408
it('change', function() {
23792409
var obj = { value: 10, str: 'foo' },
23802410
heroes = ['spiderman', 'superman'],

test/expect.js

Lines changed: 34 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3508,19 +3508,19 @@ describe('expect', function () {
35083508

35093509
err(function () {
35103510
expect({}).members([], 'blah');
3511-
}, 'blah: expected {} to be an array');
3511+
}, 'blah: expected {} to be an iterable');
35123512

35133513
err(function () {
35143514
expect({}, 'blah').members([]);
3515-
}, 'blah: expected {} to be an array');
3515+
}, 'blah: expected {} to be an iterable');
35163516

35173517
err(function () {
35183518
expect([]).members({}, 'blah');
3519-
}, 'blah: expected {} to be an array');
3519+
}, 'blah: expected {} to be an iterable');
35203520

35213521
err(function () {
35223522
expect([], 'blah').members({});
3523-
}, 'blah: expected {} to be an array');
3523+
}, 'blah: expected {} to be an iterable');
35243524
});
35253525

35263526
it('deep.members', function() {
@@ -3641,6 +3641,36 @@ describe('expect', function () {
36413641
}, 'expected [ { a: 1 }, { b: 2 }, { c: 3 } ] to not be an ordered superset of [ { a: 1 }, { b: 2 } ]');
36423642
});
36433643

3644+
it('iterable', function() {
3645+
expect([1, 2, 3]).to.be.iterable;
3646+
expect(new Map([[1, 'one'], [2, 'two'], [3, 'three']])).to.be.iterable;
3647+
expect(new Set([1, 2, 3])).to.be.iterable;
3648+
3649+
err(function() {
3650+
expect(42).to.be.iterable;
3651+
}, 'expected 42 to be an iterable');
3652+
3653+
err(function() {
3654+
expect('hello').to.be.iterable;
3655+
}, "expected 'hello' to be an iterable");
3656+
3657+
err(function() {
3658+
expect(undefined).to.be.iterable;
3659+
}, 'expected undefined to be an iterable');
3660+
3661+
err(function() {
3662+
expect(null).to.be.iterable;
3663+
}, 'expected null to be an iterable');
3664+
3665+
err(function() {
3666+
expect(true).to.be.iterable;
3667+
}, 'expected true to be an iterable');
3668+
3669+
err(function() {
3670+
expect({ key: 'value' }).to.be.iterable;
3671+
}, 'expected { key: \'value\' } to be an iterable');
3672+
})
3673+
36443674
it('change', function() {
36453675
var obj = { value: 10, str: 'foo' },
36463676
heroes = ['spiderman', 'superman'],

test/should.js

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2820,11 +2820,11 @@ describe('should', function() {
28202820

28212821
err(function() {
28222822
'foo'.should.include.members([12], 'blah');
2823-
}, "blah: expected 'foo' to be an array");
2823+
}, "blah: expected 'foo' to be an iterable");
28242824

28252825
err(function() {
28262826
[1, 2, 3].should.include.members('o', 'blah');
2827-
}, "blah: expected 'o' to be an array");
2827+
}, "blah: expected 'o' to be an iterable");
28282828
});
28292829

28302830
it('memberEquals', function() {
@@ -2845,7 +2845,7 @@ describe('should', function() {
28452845

28462846
err(function() {
28472847
[1, 2, 3].should.have.same.members(4, 'blah');
2848-
}, 'blah: expected 4 to be an array');
2848+
}, 'blah: expected 4 to be an iterable');
28492849
});
28502850

28512851
it('deep.members', function() {
@@ -2942,6 +2942,28 @@ describe('should', function() {
29422942
}, 'expected [ { a: 1 }, { b: 2 }, { c: 3 } ] to not be an ordered superset of [ { a: 1 }, { b: 2 } ]');
29432943
});
29442944

2945+
it ('iterable', function() {
2946+
([1, 2, 3]).should.be.iterable;
2947+
(new Map([[1, 'one'], [2, 'two'], [3, 'three']])).should.be.iterable;
2948+
(new Set([1, 2, 3])).should.be.iterable;
2949+
2950+
err(function() {
2951+
(42).should.be.iterable;
2952+
}, 'expected 42 to be an iterable');
2953+
2954+
err(function() {
2955+
('hello').should.be.iterable;
2956+
}, "expected 'hello' to be an iterable");
2957+
2958+
err(function() {
2959+
(true).should.be.iterable;
2960+
}, 'expected true to be an iterable');
2961+
2962+
err(function() {
2963+
({ key: 'value' }).should.be.iterable;
2964+
}, 'expected { key: \'value\' } to be an iterable');
2965+
})
2966+
29452967
it('change', function() {
29462968
var obj = { value: 10, str: 'foo' },
29472969
heroes = ['spiderman', 'superman'],

0 commit comments

Comments
 (0)