December 19, 2019
TestsSource
- Creating a generator
- Calling a generator
- Using a generator
Source Code
The source code we wrote during the event.
generators.spec.js
import assert from 'assert';
describe('Creating a generator', () => {
it('has the type of "function"', () => {
function* generator() {}
assert.equal(typeof generator, 'function');
});
it('order of asterisk does matter', () => {
function *generator() {}
assert.equal(typeof generator, 'function');
});
it('assigning an unnamed function as a generator is possible', () => {
assert.doesNotThrow(() => eval('const gen = function* () {}'));
assert.doesNotThrow(() => eval('const gen = function*() {}'));
assert.doesNotThrow(() => eval('const gen = function *() {}'));
assert.doesNotThrow(() => eval('const gen = function * () {}'));
});
it('arrow function can not be a generator', () => {
assert.throws(() => eval('const generator = *() => {};'), SyntaxError);
assert.throws(() => eval('const generator *= () => {};'), SyntaxError);
assert.throws(() => eval('const generator = ()* => {};'), SyntaxError);
assert.throws(() => eval('const generator = () => *{};'), SyntaxError);
assert.throws(() => eval('const *generator = () => {};'), SyntaxError);
});
it('stringified prototype of the generator is "[object Generator]"', () => {
function* generator() {}
assert.equal(generator.prototype.toString(), '[object Generator]');
});
});
describe('Calling a generator', () => {
it('is of type "object"', () => {
function* generator() {}
assert.equal(typeof generator(), 'object');
});
it('prototype of a called generator returns undefined', () => {
function* generator() {}
assert.equal(generator().prototype, undefined);
});
it('prototype of a called generator returns undefined', () => {
function* generator() {
yield 1;
}
assert.equal(generator().prototype, undefined);
});
it('called generator returning a string returns ???', () => {
function* generator() {
return "a string";
}
assert.notEqual(generator(), "a string");
});
it('does not execute the return statement', () => {
let a = 0;
function* generator() {
return a++;
}
generator();
assert.equal(a, 0);
});
it('does not execute function body', () => {
let a = 0;
function* generator() {
a++;
}
generator();
assert.equal(a, 0);
});
});
describe('Using a generator', () => {
it('increases `a` once when calling next() twice', () => {
let a = 0;
function* generator() {
a++;
}
const iterator = generator();
iterator.next();
assert.equal(a, 1);
iterator.next();
assert.equal(a, 1);
});
it('calling `next()` on an iterator DOES not return the original return value', () => {
function* generator() {
return 'a string';
}
assert.notEqual(generator().next(), 'a string');
});
it('return terminates the generator regardless of a yield afterwards', () => {
function* generator() {
return 0;
yield 1;
}
assert.deepStrictEqual(generator().next(), {done: true, value: 0});
});
it('does not execute things after `return`', () => {
let a = 0;
function* generator() {
return 99;
a++;
}
generator().next();
assert.strictEqual(a, 0);
});
it('yielding two values they can be read via 2x `next()`', () => {
function* generator() {
yield 1;
yield 2;
return 3;
}
const iterator = generator();
assert.deepStrictEqual(iterator.next(), {done: false, value: 1});
assert.deepStrictEqual(iterator.next(), {done: false, value: 2});
assert.deepStrictEqual(iterator.next(), {done: true, value: 3});
});
it('a `return yield 2` will terminate the iterator', () => {
function * generator() {
yield 1;
return yield 2;
}
const iterator = generator();
iterator.next();
assert.deepStrictEqual(iterator.next(), {done: false, value: 2});
});
it('the return value of a yielded value is undefined', () => {
function * generator() {
return yield 1;
}
const iterator = generator();
iterator.next();
assert.deepStrictEqual(iterator.next(), {done: true, value: undefined});
});
it('the return value of a yielded value is the value passed to previous `next()`', () => {
function * generator() {
return yield 1;
}
const iterator = generator();
iterator.next();
assert.deepStrictEqual(iterator.next(2), {done: true, value: 2});
});
it('yielding and assigning is fun, learning ...', () => {
let a = 0;
function * generator() {
a = yield 1;
yield a;
}
const iterator = generator();
assert.deepStrictEqual(iterator.next(), {done: false, value: 1});
assert.deepStrictEqual(iterator.next(), {done: false, value: undefined});
assert.deepStrictEqual(iterator.next(), {done: true, value: undefined});
assert.strictEqual(a, undefined);
});
it('yielding and assigning is fun, learning part 2 ...', () => {
let a = 0;
const b = 5;
function * generator(param) {
a = yield param;
yield a;
}
const iterator = generator(6);
assert.deepStrictEqual(iterator.next('this parameter is ignored'), {done: false, value: 6});
assert.deepStrictEqual(iterator.next(3), {done: false, value: 3});
assert.deepStrictEqual(iterator.next(), {done: true, value: undefined});
// assert.strictEqual(a, 3);
});
});