-
Notifications
You must be signed in to change notification settings - Fork 0
/
solution.js
107 lines (95 loc) · 3.43 KB
/
solution.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
// 40: iterator - one example usage. (solution)
// Build an iterable and use it with some built-in ES6 constructs.
// To do: make all tests pass, leave the assert lines unchanged!
// Consumable users:
// - `consumableUser` contains a consumable user,
// - `anyLeft` tells if there is any user left that can be consumed.
class ConsumableUsers {
constructor() {
this.users = ['Alice', 'Bob'];
this.isEmpty = false;
}
get nextUser() {
if (this.users.length > 0) {
return `user: ${this.users.shift()}`;
}
this.isEmpty = true;
return void 0;
}
get anyLeft() {
return this.isEmpty;
}
}
describe('Iterator usages', () => {
let usersIterable;
beforeEach(function(){
const consumableUsers = new ConsumableUsers();
function iteratorFunction() {
return {
next: function() {
return {value: consumableUsers.nextUser, done: consumableUsers.anyLeft}
}
}
}
usersIterable = {
[Symbol.iterator]: iteratorFunction
};
});
describe('create an iterator/iterable', function() {
it('the `usersIterable` should be iterable', function() {
const isIterable = Symbol.iterator in usersIterable;
assert.equal(isIterable, true);
});
it('the iterator of `usersIterable` should return an object', function() {
const iterator = usersIterable[Symbol.iterator]();
assert.equal(typeof iterator, 'object');
});
it('the iterator of `usersIterable` should have a next function', function() {
const iterator = usersIterable[Symbol.iterator]();
assert.equal(typeof iterator.next, 'function');
});
});
describe('fill the iterable with content using `ConsumableUsers`', function() {
describe('using the iterator', function() {
let iterator;
beforeEach(function(){
iterator = usersIterable[Symbol.iterator]();
});
it('should return `Alice` as first user', function() {
const firstItem = iterator.next();
assert.deepEqual(firstItem, {value: "user: Alice", done: false});
});
it('should return `Bob` as second user', function() {
iterator.next(); // drop the first item
const secondItem = iterator.next();
assert.deepEqual(secondItem, {value: "user: Bob", done: false});
});
it('should return `done:true`, which means there are no more items', function() {
iterator.next();
iterator.next();
const beyondLast = iterator.next();
assert.deepEqual(beyondLast, {value: void 0, done: true});
})
});
describe('using built-in constructs', function() {
it('use `Array.from()` to convert an iterable to an array', function() {
const users = Array.from(usersIterable);
assert.deepEqual(users, ['user: Alice', 'user: Bob']);
});
it('use for-of to loop over an iterable', function() {
const users = [];
for (let user of usersIterable) users.push(user);
assert.deepEqual(users, ['user: Alice', 'user: Bob']);
});
it('use the spread-operator to convert/add iterable to an array', function() {
const users = ['noname', ...usersIterable];
assert.deepEqual(users, ['noname', 'user: Alice', 'user: Bob']);
});
it('destructure an iterable like an array', function() {
const [firstUser, secondUser] = usersIterable;
assert.equal(firstUser, 'user: Alice');
assert.equal(secondUser, 'user: Bob');
})
});
});
});