Last active
February 20, 2022 02:13
-
-
Save mischah/3dfc9d1923f7f72e955189cfb0197fa2 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// http://tddbin.com/?787#?kata=es6/language/template-strings/basics | |
// 1: template strings - basics | |
// To do: make all tests pass, leave the asserts unchanged! | |
describe('a template string, is wrapped in ` (backticks) instead of \' or "', function() { | |
describe('by default, behaves like a normal string', function() { | |
it('just surrounded by backticks', function() { | |
var str = `like a string`; | |
assert.equal(str, 'like a string'); | |
}); | |
}); | |
var x = 42; | |
var y = 23; | |
describe('can evaluate variables, which are wrapped in "${" and "}"', function() { | |
it('e.g. a simple variable "${x}" just gets evaluated', function() { | |
var evaluated = `x=${x}`; | |
assert.equal(evaluated, 'x=' + x); | |
}); | |
it('multiple variables get evaluated too', function() { | |
var evaluated = `${x}+${y}`; | |
assert.equal(evaluated, x + '+' + y); | |
}); | |
}); | |
describe('can evaluate any expression, wrapped inside "${...}"', function() { | |
it('all inside "${...}" gets evaluated', function() { | |
var evaluated = `${x+y}`; | |
assert.equal(evaluated, x+y); | |
}); | |
it('inside "${...}" can also be a function call', function() { | |
function getDomain(){ | |
return document.domain; | |
} | |
var evaluated = `${getDomain()}`; | |
assert.equal(evaluated, 'tddbin.com'); | |
}); | |
}); | |
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// http://tddbin.com/?270#?kata=es6/language/template-strings/multiline | |
// 2: template strings - multiline | |
// To do: make all tests pass, leave the asserts unchanged! | |
describe('template string, can contain multiline content', function() { | |
it('a normal string can`t span across multiple lines', function() { | |
var normalString = 'line1' + | |
'\n' + | |
'line2'; | |
assert.equal(normalString, 'line1\nline2'); | |
}); | |
it('wrapped in backticks it can span over multiple lines', function() { | |
var templateString = `line1 | |
line2`; | |
assert.equal(templateString, 'line1\nline2'); | |
}); | |
it('even over more than two lines', function() { | |
var multiline = `line 1 | |
line 2 | |
line 3 | |
line 4`; | |
assert.equal(multiline.split('\n').length, 4); | |
}); | |
describe('and expressions inside work too', function() { | |
var x = 42; | |
it('like simple variables', function() { | |
var multiline = `line 1 | |
${x}`; | |
assert.equal(multiline, 'line 1\n 42'); | |
}); | |
it('also here spaces matter', function() { | |
var multiline = ` | |
${x}`; | |
assert.equal(multiline, '\n42'); | |
}); | |
}); | |
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// http://tddbin.com/?622#?kata=es6/language/template-strings/tagged | |
// 3: template strings - tagged | |
// To do: make all tests pass, leave the asserts unchanged! | |
describe('tagged template strings, are an advanced form of template strings', function() { | |
it('syntax: prefix the template string with a function to call (without "()" around it)', function() { | |
function tagFunction(s) { | |
return s.toString(); | |
} | |
var evaluated = tagFunction `template string`; | |
assert.equal(evaluated, 'template string'); | |
}); | |
describe('the function can access each part of the template', function() { | |
describe('the 1st parameter - receives only the pure strings of the template string', function() { | |
function tagFunction(strings) { | |
return strings; | |
} | |
it('the strings are an array', function() { | |
var result = ['template string']; | |
assert.deepEqual(tagFunction `template string`, result); | |
}); | |
it('expressions are NOT passed to it', function() { | |
var tagged = tagFunction `one${23}two`; | |
assert.deepEqual(tagged, ['one', 'two']); | |
}); | |
}); | |
describe('the 2nd and following parameters - contain the values of the processed substitution', function() { | |
var one = 1; | |
var two = 2; | |
var three = 3; | |
it('the 2nd parameter contains the first expression`s value', function() { | |
function firstValueOnly(strings, firstValue) { | |
return firstValue; | |
} | |
assert.equal(firstValueOnly `uno ${one}, dos ${two}`, 1); | |
}); | |
it('the 3rd parameter contains the second expression`s value', function() { | |
function firstValueOnly(strings, firstValue, secondValue) { | |
return secondValue; | |
} | |
assert.equal(firstValueOnly`uno ${one}, dos ${two}`, 2); | |
}); | |
it('using ES6 rest syntax, all values can be accessed via one variable', function() { | |
function valuesOnly(stringsArray, ...allValues) { // using the new ES6 rest syntax | |
return allValues; | |
} | |
assert.deepEqual(valuesOnly`uno=${one}, dos=${two}, tres=${three}`, [1, 2, 3]); | |
}); | |
}); | |
}); | |
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// http://tddbin.com/?243#?kata=es6/language/template-strings/raw | |
// 4: template strings - String.raw | |
// To do: make all tests pass, leave the asserts unchanged! | |
describe('on tagged template strings you can use the `raw` property like so `s.raw`', function() { | |
it('the `raw` property accesses the string as it was entered', function() { | |
function firstChar(strings) { | |
return strings.raw; | |
} | |
assert.equal(firstChar`\n`, '\\n'); | |
}); | |
it('`raw` can access the backslash of a line-break', function() { | |
function firstCharEntered(strings) { | |
var lineBreak = strings.raw.toString()[0]; | |
return lineBreak; | |
} | |
assert.equal(firstCharEntered`\n`, '\\'); | |
}); | |
describe('`String.raw` as a static function', function(){ | |
it('concats the raw strings', function() { | |
var expected = '\\n'; | |
assert.equal(String.raw`\n`, expected); | |
}); | |
it('two raw-templates-string-backslashes equal two escaped backslashes', function() { | |
const TWO_BACKSLASHES = '\\\\'; | |
assert.equal(String.raw`\\`, TWO_BACKSLASHES); | |
}); | |
it('works on unicodes too', function() { | |
var smilie = '\\u{1F600}'; | |
var actual = String.raw`\u{1F600}`; | |
assert.equal(actual, smilie); | |
}); | |
}); | |
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// http://tddbin.com/?938#?kata=es6/language/arrow-functions/basics | |
// 5: arrow functions - basics | |
// To do: make all tests pass, leave the asserts unchanged! | |
describe('arrow functions', function() { | |
it('are shorter to write', function() { | |
var func = () => { | |
return 'I am func'; | |
}; | |
assert.equal(func(), 'I am func'); | |
}); | |
it('a single expression, without curly braces returns too', function() { | |
var func = () => 'I return too'; | |
assert.equal(func(), 'I return too'); | |
}); | |
it('one parameter can be written without parens', () => { | |
var func = p => p + 1; | |
assert.equal(func(23), 24); | |
}); | |
it('many params require parens', () => { | |
var func = (param, param1) => param + param1; | |
assert.equal(func(23, 42), 23+42); | |
}); | |
it('body needs parens to return an object', () => { | |
var func = () => ({iAm: 'an object'}); | |
assert.deepEqual(func(), {iAm: 'an object'}); | |
}); | |
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// http://tddbin.com/?355#?kata=es6/language/arrow-functions/binding | |
// 6: arrow functions - binding | |
// To do: make all tests pass, leave the asserts unchanged! | |
class LexicallyBound { | |
getFunction() { | |
return () => this; | |
} | |
getArgumentsFunction() { | |
return () => arguments; | |
} | |
} | |
describe('arrow functions have lexical `this`, no dynamic `this`', () => { | |
it('bound at definition time, use `=>` ', function() { | |
var bound = new LexicallyBound(); | |
var fn = bound.getFunction(); | |
assert.strictEqual(fn(), bound); | |
}); | |
it('can NOT bind a different context', function() { | |
var bound = new LexicallyBound(); | |
var fn = bound.getFunction(); | |
var anotherObj = {}; | |
var expected = bound; | |
assert.strictEqual(fn.call(anotherObj), expected); | |
}); | |
it('`arguments` doesnt work inside arrow functions', function() { | |
var bound = new LexicallyBound(); | |
var fn = bound.getArgumentsFunction(); | |
assert.equal(fn(1, 2).length, 0); | |
}); | |
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// http://tddbin.com/?319#?kata=es6/language/block-scoping/let | |
// 7: block scope - let | |
// To do: make all tests pass, leave the asserts unchanged! | |
describe('`let` restricts the scope of the variable to the current block', () => { | |
describe('`let` vs. `var`', () => { | |
it('`var` works as usual', () => { | |
if (true) { | |
var varX = true; | |
} | |
assert.equal(varX, true); | |
}); | |
it('`let` restricts scope to inside the block', () => { | |
if (true) { | |
let letX = true; | |
} | |
assert.throws(() => console.log(letX)); | |
}); | |
}); | |
describe('`let` usage', () => { | |
it('`let` use in `for` loops', () => { | |
let obj = {x: 1}; | |
for (let key in obj) {} | |
assert.throws(() => console.log(key)); | |
}); | |
it('create artifical scope, using curly braces', () => { | |
{ | |
let letX = true; | |
} | |
assert.throws(() => console.log(letX)); | |
}); | |
}); | |
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// http://tddbin.com/?934#?kata=es6/language/block-scoping/const | |
// 8: block scope - const | |
// To do: make all tests pass, leave the asserts unchanged! | |
describe('`const` is like `let` plus read-only', () => { | |
describe('scalar values are read-only', () => { | |
it('number', () => { | |
const constNum = 0; | |
assert.equal(constNum, 0); | |
}); | |
it('string', () => { | |
const constString = 'I am a const'; | |
assert.equal(constString, 'I am a const'); | |
}); | |
}); | |
const notChangeable = 23; | |
it('const scope leaks too', () => { | |
assert.equal(notChangeable, 23); | |
}); | |
describe('complex types are NOT fully read-only', () => { | |
it('array', () => { | |
const arr = [42, 23]; | |
assert.equal(arr[0], 42); | |
}); | |
it('object', () => { | |
const obj = {x: 1}; | |
obj.x = 3; | |
assert.equal(obj.x, 3); | |
}); | |
}); | |
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// http://tddbin.com/?161#?kata=es6/language/object-literal/basics | |
// 9: object-literals - basics | |
// To do: make all tests pass, leave the assert lines unchanged! | |
describe('The object literal allows for new shorthands', () => { | |
const x = 1; | |
const y = 2; | |
describe('with variables', () => { | |
it('the short version for `{x: x}` is {x}', () => { | |
const short = {y}; | |
assert.deepEqual(short, {y: y}); | |
}); | |
it('works with multiple variables too', () => { | |
const short = {x, y}; | |
assert.deepEqual(short, {x: x, y: y}); | |
}); | |
}); | |
describe('with methods', () => { | |
const func = () => func; | |
it('using the name only uses it as key', () => { | |
const short = {func}; | |
assert.deepEqual(short, {func: func}); | |
}); | |
it('a different key must be given explicitly, just like before ES6', () => { | |
const short = {otherKey: func}; | |
assert.deepEqual(short, {otherKey: func}); | |
}); | |
it('inline functions, can written as `obj={func(){}}` instead of `obj={func:function(){}}`', () => { | |
const short = { | |
inlineFunc() { return 'I am inline'} | |
}; | |
assert.deepEqual(short.inlineFunc(), 'I am inline'); | |
}); | |
}); | |
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// http://tddbin.com/?451#?kata=es6/language/destructuring/array | |
// 10: destructuring - array | |
// To do: make all tests pass, leave the assert lines unchanged! | |
describe('destructuring arrays makes shorter code', () => { | |
it('extract value from array, e.g. extract 0 into x like so `let [x] = [0];`', () => { | |
let [firstValue] = [1]; | |
assert.strictEqual(firstValue, 1); | |
}); | |
it('swap two variables, in one operation', () => { | |
let [y, x] = ['ax', 'why']; | |
assert.deepEqual([x, y], ['why', 'ax']); | |
}); | |
it('leading commas', () => { | |
const all = ['ax', 'why', 'zet']; | |
const [,,z] = all; | |
assert.equal(z, 'zet'); | |
}); | |
it('extract from nested arrays', () => { | |
const user = [['Some', 'One'], 23]; | |
const [[firstName, surname], age] = user; | |
const expected = 'Some One = 23 years'; | |
assert.equal(`${firstName} ${surname} = ${age} years`, expected); | |
}); | |
it('chained assignments', () => { | |
let c, d; | |
let [a, b] = [c, d] = [1, 2]; | |
assert.deepEqual([a, b, c, d], [1, 2, 1, 2]); | |
}); | |
it('in for-of loop', () => { | |
for (var [,a, b] of [[0, 1, 2]]) {} | |
assert.deepEqual([a, b], [1, 2]); | |
}); | |
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// http://tddbin.com/?808#?kata=es6/language/destructuring/string | |
// 11: destructuring - string | |
// To do: make all tests pass, leave the assert lines unchanged! | |
describe('destructuring also works on strings', () => { | |
it('destructure every character', () => { | |
let [a, b, c] = 'abc'; | |
assert.deepEqual([a, b, c], ['a', 'b', 'c']); | |
}); | |
it('missing characters are undefined', () => { | |
const [a, b, c] = 'ab'; | |
assert.equal(c, void 0); | |
}); | |
it('unicode character work too', () => { | |
const [, , coffee] = 'a ☕'; | |
assert.equal(coffee, '\u{2615}'); | |
}); | |
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// http://tddbin.com/#?kata=es6/language/destructuring/object | |
// 12: destructuring - object | |
// To do: make all tests pass, leave the assert lines unchanged! | |
describe('destructuring objects', () => { | |
it('is simple', () => { | |
const object = {x: 1}; | |
const {x} = object; | |
assert.equal(x, 1); | |
}); | |
describe('nested', () => { | |
it('multiple objects', () => { | |
const magic = {first: 23, second: 42}; | |
const {magic: {second}} = {magic}; | |
assert.equal(second, 42); | |
}); | |
it('object and array', () => { | |
const {z:[,x]} = {z: [23, 42]}; | |
assert.equal(x, 42); | |
}); | |
it('array and object', () => { | |
const [,[{lang}]] = [null, [{env: 'browser', lang: 'ES6'}]]; | |
assert.equal(lang, 'ES6'); | |
}); | |
}); | |
describe('interesting', () => { | |
it('missing refs become undefined', () => { | |
const {z} = {x: 1, y: 2}; | |
assert.equal(z, void 0); | |
}); | |
it('destructure from builtins (string)', () => { | |
const {substr} = String.prototype; | |
assert.equal(substr, String.prototype.substr); | |
}); | |
}); | |
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// http://tddbin.com/#?kata=es6/language/destructuring/defaults | |
// 13: destructuring - defaults | |
// To do: make all tests pass, leave the assert lines unchanged! | |
describe('destructuring can also have default values', () => { | |
it('for an empty array', () => { | |
const [a=1] = []; | |
assert.equal(a, 1); | |
}); | |
it('for a missing value', () => { | |
const [a,b=2,c] = [1,,3]; | |
assert.equal(b, 2); | |
}); | |
it('in an object', () => { | |
const {a, b=2} = {a: 1}; | |
assert.equal(b, 2); | |
}); | |
it('if the value is undefined', () => { | |
const {a, b=2} = {a: 1, b: void 0}; | |
assert.strictEqual(b, 2); | |
}); | |
it('also a string works with defaults', () => { | |
const [a, b=2] = '1'; | |
assert.equal(a, '1'); | |
assert.equal(b, 2); | |
}); | |
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// http://tddbin.com/#?kata=es6/language/destructuring/parameters | |
// 14: destructuring - parameters | |
// To do: make all tests pass, leave the assert lines unchanged! | |
describe('destructuring function parameters', () => { | |
describe('destruct parameters', () => { | |
it('multiple params from object', () => { | |
const fn = ({name, id}) => { | |
assert.equal(id, 42); | |
assert.equal(name, 'Wolfram'); | |
}; | |
const user = {name: 'Wolfram', id: 42}; | |
fn(user); | |
}); | |
it('multiple params from array/object', () => { | |
const fn = ([,{name}]) => { | |
assert.equal(name, 'Alice'); | |
}; | |
const users = [{name: 'nobody'}, {name: 'Alice', id: 42}]; | |
fn(users); | |
}); | |
}); | |
describe('default values', () => { | |
it('for simple values', () => { | |
const fn = ({id, name='Bob'}) => { | |
assert.strictEqual(id, 23); | |
assert.strictEqual(name, 'Bob'); | |
}; | |
fn({id:23}); | |
}); | |
it('for a missing array value', () => { | |
const defaultUser = {id: 23, name: 'Joe'}; | |
const fn = ([user=defaultUser]) => { | |
assert.deepEqual(user, defaultUser); | |
}; | |
fn([]); | |
}); | |
it('mix of parameter types', () => { | |
const fn = (id=1, [arr=2], {obj=3}) => { | |
assert.equal(id, 1); | |
assert.equal(arr, 2); | |
assert.equal(obj, 3); | |
}; | |
fn(void 0, [], {}); | |
}); | |
}); | |
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// http://tddbin.com/#?kata=es6/language/destructuring/rename | |
// 15: destructuring - assign | |
// To do: make all tests pass, leave the assert lines unchanged! | |
describe('assign object property values to new variables while destructuring', () => { | |
describe('for simple objects', function() { | |
it('use a colon after the property name, like so `propertyName: newName`', () => { | |
const {x: y} = {x: 1}; | |
assert.equal(y, 1); | |
}); | |
it('assign a new name and give it a default value using `= <default value>`', () => { | |
const {x: y=42} = {y: 23}; | |
assert.equal(y, 42); | |
}); | |
}); | |
describe('for function parameter names', function() { | |
it('do it the same way, with a colon behind it', () => { | |
const fn = ({x:y}) => { | |
assert.equal(y, 1); | |
}; | |
fn({x: 1}); | |
}); | |
it('giving it a default value is possible too, like above', () => { | |
const fn = ({x: y=3}) => { | |
assert.equal(y, 3); | |
}; | |
fn({}); | |
}); | |
}); | |
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// http://tddbin.com/#?kata=es6/language/object-literal/computed-properties | |
// 16: object-literal - computed properties | |
// To do: make all tests pass, leave the assert lines unchanged! | |
describe('Object literal properties may be computed values', () => { | |
it('a computed property `x` needs to be surrounded by `[]`', () => { | |
const propertyName = 'x'; | |
const obj = {[propertyName]: 1}; | |
assert.equal(obj.x, 1); | |
}); | |
it('can also get a function assigned', () => { | |
const key = 'func'; | |
const obj = {[key]: () => 'seven' }; | |
assert.equal(obj.func(), 'seven'); | |
}); | |
it('the key may also be the result of a function call', () => { | |
const getName = () => 'propertyName'; | |
const obj = {[getName()]() {return 'seven'}}; | |
assert.equal(obj.propertyName(), 'seven'); | |
}); | |
it('the key can also be constructed by an expression', () => { | |
const what = 'Name'; | |
const obj = {['property' + what]: null}; | |
assert.equal('propertyName' in obj, true); | |
}); | |
it('accessor keys can be computed names too', () => { | |
const obj = { | |
get ['key']() {return 1} | |
}; | |
assert.equal(obj.key, 1); | |
}); | |
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// http://tddbin.com/?793#?kata=es6/language/unicode/in-strings | |
// 17: unicode - in strings | |
// To do: make all tests pass, leave the assert lines unchanged! | |
describe('unicode strings', () => { | |
it('are \\u prefixed', () => { | |
const nuclear = '\u2622'; | |
assert.equal(nuclear, '☢'); | |
}); | |
it('value is 4 bytes/digits', () => { | |
const nuclear = '\u2622'; | |
assert.equal(`no more ${nuclear}`, 'no more ☢'); | |
}); | |
it('value is hexadecimal', () => { | |
const nuclear = `\u006E\u006F more \u2622`; | |
assert.equal(nuclear, 'no more ☢'); | |
}); | |
it('curly braces may surround the value', () => { | |
const nuclear = `\u{006E}\u{006F} more \u2622`; | |
assert.equal(nuclear, 'no more ☢'); | |
}); | |
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// http://tddbin.com/?389#?kata=es6/language/rest/as-parameter | |
// 18: rest - as-parameter | |
// To do: make all tests pass, leave the assert lines unchanged! | |
describe('rest in function params', () => { | |
it('must be the last parameter', () => { | |
const fn = (first, ...rest) => { | |
assert.deepEqual([1, 2], rest); | |
}; | |
fn(0, 1, 2); | |
}); | |
it('can be used to get all other parameters', () => { | |
const fn = (firstParam, secondParam, ...rest) => { | |
assert.deepEqual([3,4], rest); | |
}; | |
fn(null, 2, 3, 4); | |
}); | |
it('makes `arguments` obsolete', () => { | |
const fn = (...args) => { | |
assert.deepEqual([42, 'twenty three', 'win'], args); | |
}; | |
fn(42, 'twenty three', 'win'); | |
}); | |
it('eliminate `arguments`!!!', () => { | |
const fn = (first, ...rest) => rest; | |
const rest = fn(1, 2, 3); | |
assert.deepEqual([2, 3], rest); | |
}); | |
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// http://tddbin.com/?375#?kata=es6/language/rest/with-destructuring | |
// 19: rest - with-destructuring | |
// To do: make all tests pass, leave the assert lines unchanged! | |
describe('rest with destructuring', () => { | |
it('rest parameter must be last', () => { | |
const [...all] = [1, 2, 3, 4]; | |
assert.deepEqual(all, [1, 2, 3, 4]); | |
}); | |
it('assign rest of an array to a variable', () => { | |
const [first, ...all] = [1, 2, 3, 4]; | |
assert.deepEqual(all, [2, 3, 4]); | |
}); | |
// the following are actually using `spread` ... oops, to be fixed | |
it('concat differently', () => { | |
const theEnd = [3, 4]; | |
const allInOne = [1, 2, ...theEnd]; | |
assert.deepEqual(allInOne, [1, 2, 3, 4]); | |
}); | |
it('`apply` made simple, even for constructors', () => { | |
const theDate = [2015, 1, 1]; | |
const date = new Date(...theDate); | |
assert.deepEqual(new Date(2015, 1, 1), date); | |
}); | |
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// http://tddbin.com/#?kata=es6/language/spread/with-arrays | |
// 20: spread - with-arrays | |
// To do: make all tests pass, leave the assert lines unchanged! | |
describe('spread with arrays', () => { | |
it('extracts each array item', function() { | |
const [a, b] = [...[1, 2]]; | |
assert.equal(a, 1); | |
assert.equal(b, 2); | |
}); | |
it('in combination with rest', function() { | |
const [a, b, ...rest] = [...[1, 2, 3, 4, 5]]; | |
assert.equal(a, 1); | |
assert.equal(b, 2); | |
assert.deepEqual(rest, [3, 4, 5]); | |
}); | |
it('spreading into the rest', function() { | |
const [...rest] = [...[1, 2, 3, 4, 5]]; | |
assert.deepEqual(rest, [1, 2, 3, 4, 5]); | |
}); | |
describe('used as function parameter', () => { | |
it('prefix with `...` to spread as function params', function() { | |
const magicNumbers = [1, 2]; | |
const fn = (magicA, magicB) => { | |
assert.deepEqual(magicNumbers[0], magicA); | |
assert.deepEqual(magicNumbers[1], magicB); | |
}; | |
fn(...magicNumbers); | |
}); | |
it('pass an array of numbers to Math.max()', function() { | |
const max = Math.max(...[23, 0, 42]); | |
assert.equal(max, 42); | |
}); | |
}); | |
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// http://tddbin.com/#?kata=es6/language/spread/with-strings | |
// 21: spread - with-strings | |
// To do: make all tests pass, leave the assert lines unchanged! | |
describe('spread with strings', () => { | |
it('simply spread each char of a string', function() { | |
const [a, b] = [...'ab']; | |
assert.equal(a, 'a'); | |
assert.equal(b, 'b'); | |
}); | |
it('extracts each array item', function() { | |
const [,a,b] = ['a', ...'12']; | |
assert.equal(a, 1); | |
assert.equal(b, 2); | |
}); | |
it('works anywhere inside an array (must not be last)', function() { | |
const letters = [...'a', ...'bcd', ...'e', ...'f']; | |
assert.equal(letters.length, 6); | |
}); | |
it('dont confuse with the rest operator', function() { | |
const rest = [...'1234', ...'5']; | |
assert.deepEqual(rest, [1, 2, 3, 4, 5]); | |
}); | |
it('passed as function parameter', function() { | |
const max = Math.max(...[1,2,3,4,5]); | |
assert.deepEqual(max, 5); | |
}); | |
}); | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// http://tddbin.com/?953#?kata=es6/language/class/creation | |
// 22: class - creation | |
// To do: make all tests pass, leave the assert lines unchanged! | |
describe('class creation', () => { | |
it('is as simple as `class XXX {}`', function() { | |
class TestClass {}; | |
const instance = new TestClass(); | |
assert.equal(typeof instance, 'object'); | |
}); | |
it('class is block scoped', () => { | |
class Outside {} | |
{ class Inside {} } | |
assert.equal(typeof Inside, 'undefined'); | |
}); | |
it('special method is `constructor`', function() { | |
class User { | |
constructor(id) { | |
this.id = id; | |
} | |
} | |
const user = new User(42); | |
assert.equal(user.id, 42); | |
}); | |
it('defining a method is simple', function() { | |
class User { | |
writesTests() { return false; } | |
} | |
const notATester = new User(); | |
assert.equal(notATester.writesTests(), false); | |
}); | |
it('multiple methods need no commas (opposed to object notation)', function() { | |
class User { | |
wroteATest() { this.everWroteATest = true; } | |
isLazy() { | |
if (this.everWroteATest === true) { | |
return false; | |
} | |
return true; | |
} | |
} | |
const tester = new User(); | |
assert.equal(tester.isLazy(), true); | |
tester.wroteATest(); | |
assert.equal(tester.isLazy(), false); | |
}); | |
it('anonymous class', () => { | |
const classType = typeof class {}; | |
assert.equal(classType, 'function'); | |
}); | |
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// http://tddbin.com/#?kata=es6/language/class/accessors | |
// 23: class - accessors | |
// To do: make all tests pass, leave the assert lines unchanged! | |
describe('class accessors (getter and setter)', () => { | |
it('only a getter is defined like a method prefixed with `get`', () => { | |
class MyAccount { | |
get balance() { return Infinity; } | |
} | |
assert.equal(new MyAccount().balance, Infinity); | |
}); | |
it('a setter has the prefix `set`', () => { | |
class MyAccount { | |
get balance() { return this.amount; } | |
set balance(amount) { this.amount = amount; } | |
} | |
const account = new MyAccount(); | |
account.balance = 23; | |
assert.equal(account.balance, 23); | |
}); | |
describe('dynamic accessors', () => { | |
it('a dynamic getter name is enclosed in [ and ]', function() { | |
const balance = 'yourMoney'; | |
class YourAccount { | |
get [balance]() { return -Infinity; } | |
} | |
assert.equal(new YourAccount().yourMoney, -Infinity); | |
}); | |
it('a dynamic setter name as well', function() { | |
const propertyName = 'balance'; | |
class MyAccount { | |
get [propertyName]() { return this.amount; } | |
set [propertyName](amount) { this.amount = 23; } | |
} | |
const account = new MyAccount(); | |
account.balance = 23; | |
assert.equal(account.balance, 23); | |
}); | |
}); | |
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// http://tddbin.com/#?kata=es6/language/class/static | |
// 24: class - static keyword | |
// To do: make all tests pass, leave the assert lines unchanged! | |
describe('inside a class you can use the `static` keyword', () => { | |
describe('for methods', () => { | |
class IntegrationTest {} | |
class UnitTest {} | |
it('a static method just has the prefix `static`', () => { | |
class TestFactory { | |
static makeTest() { return new UnitTest(); } | |
} | |
assert.ok(TestFactory.makeTest() instanceof UnitTest); | |
}); | |
it('the method name can be dynamic/computed at runtime', () => { | |
const methodName = 'createTest'; | |
class TestFactory { | |
static [methodName]() { return new UnitTest(); } | |
} | |
assert.ok(TestFactory.createTest() instanceof UnitTest); | |
}); | |
}); | |
describe('for accessors', () => { | |
it('a getter name can be static, just prefix it with `static`', () => { | |
class UnitTest { | |
static get testType() { return 'unit'; } | |
} | |
assert.equal(UnitTest.testType, 'unit'); | |
}); | |
it('even a static getter name can be dynamic/computed at runtime', () => { | |
const type = 'test' + 'Type'; | |
class IntegrationTest { | |
static get [type]() { return 'integration'; } | |
} | |
assert.ok('testType' in IntegrationTest); | |
assert.equal(IntegrationTest.testType, 'integration'); | |
}); | |
}); | |
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// http://tddbin.com/#?kata=es6/language/class/extends | |
// 25: class - extends | |
// To do: make all tests pass, leave the assert lines unchanged! | |
describe('classes can inherit from another', () => { | |
describe('the default super class is Object', () => { | |
it('class A is an instance of Object', () => { | |
class A {} | |
assert.equal(new A() instanceof Object, true); | |
}); | |
it('B extends A, B is also instance of Object', () => { | |
class A {} | |
class B extends A {} | |
assert.equal(new B() instanceof A, true); | |
assert.equal(new B() instanceof Object, true); | |
}); | |
it('class can extend `null`, not an instance of Object', () => { | |
class NullClass extends null {} | |
let nullInstance = new NullClass(); | |
assert.equal(nullInstance instanceof Object, false); | |
}); | |
}); | |
describe('instance of', () => { | |
it('when B inherits from A, `new B()` is also an instance of A', () => { | |
class A {}; | |
class B extends A {} | |
assert.equal(new B() instanceof A, true); | |
}); | |
it('extend over multiple levels', () => { | |
class A {} | |
class B extends A {} | |
class C extends B {} | |
let instance = new C(); | |
assert.equal(instance instanceof A, true); | |
}); | |
}); | |
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// http://tddbin.com/#?kata=es6/language/class/more-extends | |
// 26: class - more-extends | |
// To do: make all tests pass, leave the assert lines unchanged! | |
describe('class can inherit from another', () => { | |
it('extend an `old style` "class", a function, still works', () => { | |
function A () {} | |
class B extends A {} | |
assert.equal(new B() instanceof A, true); | |
}); | |
describe('prototypes are as you know them', () => { | |
class A { } | |
class B extends A {} | |
it('A is the prototype of B', () => { | |
const isIt = A.isPrototypeOf(B); | |
assert.equal(isIt, true); | |
}); | |
it('A`s prototype is also B`s prototype', () => { | |
const proto = B.prototype; | |
// Remember: don't touch the assert!!! :) | |
assert.equal(A.prototype.isPrototypeOf(proto), true); | |
}); | |
}); | |
describe('`extends` using an expression', () => { | |
it('eg the inline assignment of the parent class', () => { | |
let A; | |
class B extends (A = class {}) {} | |
assert.equal(new B() instanceof A, true); | |
}); | |
it('or calling a function that returns the parent class', () => { | |
const returnParent = (beNull) => beNull ? null : class {}; | |
class B extends (returnParent(true)) {} | |
assert.equal(Object.getPrototypeOf(B.prototype), null); | |
}); | |
}); | |
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// http://tddbin.com/#?kata=es6/language/class/super-in-method | |
// 27: class - super inside a method | |
// To do: make all tests pass, leave the assert lines unchanged! | |
describe('inside a class use `super` to access parent methods', () => { | |
it('use of `super` without `extends` fails (already when transpiling)', () => { | |
// class A {hasSuper() { return super; }} | |
// assert.equal(new A().hasSuper(), false); | |
}); | |
it('`super` with `extends` calls the method of the given name of the parent class', () => { | |
class A { hasSuper() { return true; } } | |
class B extends A { hasSuper() { return super.hasSuper(); } } | |
assert.equal(new B().hasSuper(), true); | |
}); | |
it('when overridden a method does NOT automatically call its super method', () => { | |
class A { hasSuper() { return true; } } | |
class B extends A { hasSuper() {}} | |
assert.equal(new B().hasSuper(), void 0); | |
}); | |
it('`super` works across any number of levels of inheritance', () => { | |
class A { iAmSuper() { return this.youAreSuper; } } | |
class B extends A { constructor() { super(); this.youAreSuper = true; } } | |
class C extends B { | |
iAmSuper() { | |
return super.iAmSuper(); | |
} | |
} | |
assert.equal(new C().iAmSuper(), true); | |
}); | |
it('accessing an undefined member of the parent class returns `undefined`', () => { | |
class A {} | |
class B extends A { getMethod() { return super.constructor(); } } | |
assert.equal(new B().getMethod(), void 0); | |
}); | |
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// http://tddbin.com/#?kata=es6/language/class/super-in-constructor | |
// 28: class - super in constructor | |
// To do: make all tests pass, leave the assert lines unchanged! | |
describe('class', () => { | |
it('if you `extend` a class, use `super()` to call the parent constructor', () => { | |
class A {constructor() { this.levels = 1; }} | |
class B extends A { | |
constructor() { | |
super(); | |
this.levels++; | |
} | |
} | |
assert.equal(new B().levels, 2); | |
}); | |
it('`super()` may also take params', () => { | |
class A {constructor(startValue=1, addTo=1) { this.counter = startValue + addTo; }} | |
class B extends A { | |
constructor(...args) { | |
super(43); | |
this.counter++; | |
} | |
} | |
assert.equal(new B(42, 2).counter, 45); | |
}); | |
it('it is important where you place your `super()` call!', () => { | |
class A {inc() { this.countUp = 1; }} | |
class B extends A { | |
inc() { | |
super.inc(); | |
this.countUp = 2; | |
super.inc(); | |
return this.countUp; | |
} | |
} | |
assert.equal(new B().inc(), 1); | |
}); | |
it('use `super.constructor` to find out if there is a parent constructor', () => { | |
class A extends null { | |
constructor() { | |
super(); | |
this.isTop = !super.constructor; | |
} | |
} | |
assert.equal(new A().isTop, false); | |
}); | |
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// http://tddbin.com/#?kata=es6/language/array-api/from | |
// 29: array - `Array.from` static method | |
// To do: make all tests pass, leave the assert lines unchanged! | |
describe('`Array.from` converts an array-like object or list into an Array', () => { | |
const arrayLike = {0: 'one', 1: 'two', length: 2}; | |
it('call `Array.from` with an array-like object', function() { | |
const arr = Array.from(arrayLike); | |
assert.deepEqual(arr, ['one', 'two']); | |
}); | |
it('a DOM node`s classList object can be converted', function() { | |
document.body.classList.add('some'); | |
document.body.classList.add('other'); | |
const classList = Array.from(document.body.classList); | |
assert.equal(''+classList, ''+['some', 'other']); | |
}); | |
it('convert a NodeList to an Array and `filter()` works on it', function() { | |
const nodeList = document.querySelectorAll('body'); | |
const bodies = Array.from(nodeList).filter((node) => node === document.body); | |
assert.deepEqual(bodies, [document.body]); | |
}); | |
describe('custom conversion using a map function as second param', () => { | |
it('we can modify the value before putting it in the array', function() { | |
const arr = Array.from(arrayLike, (value) => value.toUpperCase()); | |
assert.deepEqual(arr, ['ONE', 'TWO']); | |
}); | |
it('and we also get the object`s key as second parameter', function() { | |
const arr = Array.from(arrayLike, (value, key) => `${key}=${value}`); | |
assert.deepEqual(arr, ['0=one', '1=two']); | |
}); | |
}); | |
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// http://tddbin.com/#?kata=es6/language/array-api/of | |
// 30: array - `Array.of` static method | |
// To do: make all tests pass, leave the assert lines unchanged! | |
describe('`Array.of` creates an array with the given arguments as elements', () => { | |
it('dont mix it up with `Array(10)`, where the argument is the array length', () => { | |
const arr = Array.of(10); | |
assert.deepEqual(arr, [10]); | |
}); | |
it('puts all arguments into array elements', () => { | |
const arr = Array.of(1,2); | |
assert.deepEqual(arr, [1, 2]); | |
}); | |
it('takes any kind and number of arguments', () => { | |
const starter = [1, 2]; | |
const end = [3, '4']; | |
const arr = Array.of([...starter], ...end); | |
assert.deepEqual(arr, [[1, 2], 3, '4']); | |
}); | |
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// http://tddbin.com/#?kata=es6/language/array-api/fill | |
// 31: array - `Array.prototype.fill` method | |
// To do: make all tests pass, leave the assert lines unchanged! | |
describe('`Array.prototype.fill` can fill up an array with one value', () => { | |
it('`fill(0)` will populate `0` into each array element', function() { | |
const arr = new Array(3).fill(0); | |
assert.deepEqual(arr, [0, 0, 0]); | |
}); | |
it('fill only changes content, adds no new elements', function() { | |
const arr = [].fill(); | |
assert.deepEqual(arr, []); | |
}); | |
it('second parameter to `fill()` is the position where to start filling', function() { | |
const fillPosition = 2; | |
const arr = [1,2,3].fill(42, fillPosition); | |
assert.deepEqual(arr, [1, 2, 42]); | |
}); | |
it('third parameter is the position where filling stops', function() { | |
const fillStartAt = 1; | |
const fillEndAt = 2; | |
const arr = [1,2,3].fill(42, fillStartAt, fillEndAt); | |
assert.deepEqual(arr, [1, 42, 3]); | |
}); | |
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// http://tddbin.com/#?kata=es6/language/array-api/find | |
// 32: array - `Array.prototype.find` | |
// To do: make all tests pass, leave the assert lines unchanged! | |
describe('`Array.prototype.find` makes finding items in arrays easier', () => { | |
it('takes a compare function', function() { | |
const found = [false, true].find(value => value === true); | |
assert.equal(found, true); | |
}); | |
it('returns the first value found', function() { | |
const found = [2, 3].find((item, index) => index === 0); | |
assert.equal(found, 2); | |
}); | |
it('returns `undefined` when nothing was found', function() { | |
const found = [].find(item => item === 2); | |
assert.equal(found, void 0); | |
}); | |
it('combined with destructuring complex compares become short', function() { | |
const bob = {name: 'Bob'}; | |
const alice = {name: 'Alice'}; | |
const found = [bob, alice].find(person => person.name === 'Alice'); | |
assert.equal(found, alice); | |
}); | |
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// http://tddbin.com/#?kata=es6/language/array-api/findIndex | |
// 33: array - `Array.prototype.findIndex` | |
// To do: make all tests pass, leave the assert lines unchanged! | |
describe('`Array.prototype.findIndex` makes finding items in arrays easier', () => { | |
it('takes a compare function, returns the index where it returned true', function() { | |
const foundAt = [false, true].findIndex(item => item === true); | |
assert.equal(foundAt, 1); | |
}); | |
it('returns the first position it was found at', function() { | |
const foundAt = [0, 1, 1, 1].findIndex(item => item === 1); | |
assert.equal(foundAt, 1); | |
}); | |
it('returns `-1` when nothing was found', function() { | |
const foundAt = [1, 2, 3].findIndex(item => item > 3); | |
assert.equal(foundAt, -1); | |
}); | |
it('the findIndex callback gets the item, index and array as arguments', function() { | |
const three = 3; | |
const containsThree = arr => arr.indexOf(three) > -1; | |
function theSecondThree(element, index, arr) { | |
const preceedingItems = arr.slice(0, index); | |
return containsThree(preceedingItems); | |
} | |
const foundAt = [1, 1, 2, 3, 3, 3].findIndex(theSecondThree); | |
assert.equal(foundAt, 4); | |
}); | |
it('combined with destructuring complex compares become short', function() { | |
const bob = {name: 'Bob'}; | |
const alice = {name: 'Alice'}; | |
const foundAt = [bob, alice].findIndex(({name}) => name === 'Alice'); | |
assert.equal(foundAt, 1); | |
}); | |
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// http://tddbin.com/#?kata=es6/language/symbol/basics | |
// 34: symbol | |
// A symbol is a unique and immutable data type and may be used as an identifier for object properties | |
// read more at https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol | |
// To do: make all tests pass, leave the assert lines unchanged! | |
describe('Symbol', function() { | |
it('`Symbol` lives in the global scope', function(){ | |
const expected = window.Symbol; | |
assert.equal(Symbol, expected); | |
}); | |
it('every `Symbol()` is unique', function(){ | |
const sym1 = Symbol(); | |
const sym2 = Symbol(); | |
assert.notEqual(sym1, sym2); | |
}); | |
it('every `Symbol()` is unique, also with the same parameter', function(){ | |
var sym1 = Symbol('foo'); | |
var sym2 = Symbol('foo'); | |
assert.notEqual(sym1, sym2); | |
}); | |
it('`typeof Symbol()` returns "symbol"', function(){ | |
const theType = typeof Symbol(); | |
assert.equal(theType, 'symbol'); | |
}); | |
it('`new Symbol()` throws an exception, to prevent creation of Symbol wrapper objects', function(){ | |
function fn() { | |
new Symbol(); | |
} | |
assert.throws(fn); | |
}); | |
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// http://tddbin.com/#?kata=es6/language/symbol/for | |
// 35: Symbol.for - retrieves or creates a runtime-wide symbol | |
// To do: make all tests pass, leave the assert lines unchanged! | |
describe('`Symbol.for` for registering Symbols globally', function() { | |
it('creates a new symbol (check via `typeof`)', function() { | |
const symbolType = typeof Symbol.for('symbol name'); | |
assert.equal(symbolType, 'symbol'); | |
}); | |
it('stores the symbol in a runtime-wide registry and retrieves it from it', function() { | |
const sym = Symbol.for('new symbol'); | |
const sym1 = Symbol.for('new symbol'); | |
assert.equal(sym, sym1); | |
}); | |
it('is different to `Symbol()` which creates a symbol every time and does not store it', function() { | |
var localSymbol = Symbol.for('new symbol'); | |
var globalSymbol = Symbol('new symbol'); | |
assert.notEqual(globalSymbol, localSymbol); | |
}); | |
describe('`.toString()` on a Symbol', function() { | |
const localSymbol = Symbol('new symbol'); | |
const symbolFromRegistry = Symbol.for('new symbol'); | |
it('also contains the key given to `Symbol.for()`', function() { | |
const description = symbolFromRegistry.toString(); | |
assert.equal(description, 'Symbol(new symbol)'); | |
}); | |
describe('NOTE: the description of two different symbols', function() { | |
it('might be the same', function() { | |
const localDescription = localSymbol.toString(); | |
const fromRegistryDescription = symbolFromRegistry.toString(); | |
assert.equal(localDescription, fromRegistryDescription); | |
}); | |
it('but the symbols are not the same!', function() { | |
assert.notEqual(localSymbol, symbolFromRegistry); | |
}); | |
}); | |
}); | |
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// http://tddbin.com/#?kata=es6/language/symbol/keyFor | |
// 36: Symbol.keyFor - retrieves a shared symbol key from the global symbol registry | |
// To do: make all tests pass, leave the assert lines unchanged! | |
describe('`Symbol.keyFor()` gets the symbol key for a given symbol', function() { | |
const sym = Symbol.for('foo'); | |
it('pass the symbol to `keyFor()` and you get its key', function() { | |
const key = Symbol.keyFor(sym); | |
assert.equal(key, 'foo'); | |
}); | |
it('local symbols are not in the runtime-wide registry', function() { | |
// hint: `Symbol()` creates a local symbol! | |
const localSymbol = Symbol('foo'); | |
const key = Symbol.keyFor(localSymbol); | |
assert.equal(key, void 0); | |
}); | |
it('well-known symbols are not in the runtime-wide registry either', function() { | |
const key = Symbol.keyFor(Symbol.iterator); | |
assert.equal(key, void 0); | |
}); | |
it('for non-Symbols throws an error', function() { | |
function fn() { | |
Symbol.keyFor(unknown); | |
} | |
assert.throws(fn); | |
}); | |
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// http://tddbin.com/#?kata=es6/language/iterator/array | |
// 37: iterator/iterable - array. | |
// The iterator protocol defines a standard way to produce a sequence of values (either finite or infinite). | |
// read more at https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Iteration_protocols | |
// To do: make all tests pass, leave the assert lines unchanged! | |
describe('array is a built-in iterable object', function() { | |
const arr = ['a', 'B', 'see']; | |
describe('the iterator', function() { | |
it('an array has an iterator, which is a function', function() { | |
const iterator = arr[Symbol.iterator]; | |
const theType = typeof iterator; | |
const expected = 'function'; | |
assert.equal(theType, expected); | |
}); | |
it('can be looped with `for-of`, which expects an iterable', function() { | |
let count = 0; | |
for (let value of arr) { | |
count++; | |
} | |
assert.equal(count, arr.length); | |
}); | |
}); | |
describe('the iterator protocol', function() { | |
it('calling `next()` on an iterator returns an object according to the iterator protocol', function() { | |
const iterator = arr[Symbol.iterator](); | |
const firstItem = iterator.next(); | |
assert.deepEqual(firstItem, {done: false, value: 'a'}); | |
}); | |
it('the after-last element has done=true', function() { | |
const arr = []; | |
const iterator = arr[Symbol.iterator](); | |
const afterLast = iterator.next(); | |
assert.deepEqual(afterLast, {done: true, value: void 0}); | |
}); | |
}); | |
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// http://tddbin.com/#?kata=es6/language/iterator/string | |
// 38: iterator/iterable - string. | |
// The iterator protocol defines a standard way to produce a sequence of values (either finite or infinite). | |
// read more at https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Iteration_protocols | |
// To do: make all tests pass, leave the assert lines unchanged! | |
describe('string is a built-in iterable object', function() { | |
const s = 'abc'; | |
describe('string is iterable', function() { | |
it('the string`s object key `Symbol.iterator` is a function', function() { | |
const isA = typeof s[Symbol.iterator]; | |
assert.equal(isA, 'function'); | |
}); | |
it('use `Array.from()` to make an array out of any iterable', function(){ | |
const arr = Array.from(s); | |
assert.deepEqual(arr, ['a', 'b', 'c']); | |
}); | |
}); | |
describe('a string`s iterator', function() { | |
let iterator; | |
beforeEach(function() { | |
iterator = s[Symbol.iterator](); | |
}); | |
it('has a special string representation', function(){ | |
const description = iterator.toString(); | |
assert.equal(description, '[object String Iterator]'); | |
}); | |
it('`iterator.next()` returns an object according to the iterator protocol', function(){ | |
const value = iterator.next(); | |
assert.deepEqual(value, {done: false, value: 'a'}); | |
}); | |
it('the after-last call to `iterator.next()` says done=true, no more elements', function(){ | |
iterator.next(); | |
iterator.next(); | |
iterator.next(); | |
assert.equal(iterator.next().done, true); | |
}); | |
}); | |
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// http://tddbin.com/#?kata=es6/language/iterator/protocol | |
// 39: iterator - custom. Iterable is a protocol, when implemented allows objects | |
// to customize their iteration behavior, such as what values are looped over in a for..of construct. | |
// read more at https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Iteration_protocols | |
// To do: make all tests pass, leave the assert lines unchanged! | |
// Follow the hints of the failure messages! | |
describe('A simple iterable without items inside, implementing the right protocol', () => { | |
function iteratorFunction() { | |
return { | |
next: function() { | |
return {done: true}; | |
} | |
}; | |
} | |
describe('the `iteratorFunction` needs to comply to the iterator protocol', function() { | |
it('must return an object', function() { | |
assert.equal(typeof iteratorFunction(), 'object'); | |
}); | |
it('the object must have a function assigned to a key `next`', function() { | |
assert.equal(typeof iteratorFunction().next, 'function'); | |
}); | |
it('calling `next()` must return an object with `{done: true}`', function() { | |
assert.deepEqual(iteratorFunction().next(), {done: true}); | |
}); | |
}); | |
let iterable = {}; | |
iterable[Symbol.iterator] = iteratorFunction; | |
beforeEach(function() { | |
iterable; | |
}); | |
describe('the iterable', function() { | |
it('must be an object', function() { | |
assert.equal(typeof iterable, 'object'); | |
}); | |
it('must have the iterator function assigned to the key `Symbol.iterator`', function() { | |
assert.equal(iterable[Symbol.iterator], iteratorFunction); | |
}); | |
}); | |
describe('using the iterable', function() { | |
it('it contains no values', function() { | |
let values = ''; | |
for (let value of iterable) { | |
values += value; | |
} | |
assert.equal(values, ''); | |
}); | |
it('has no `.length` property', function() { | |
const hasLengthProperty = iterable.length || false; | |
assert.equal(hasLengthProperty, false); | |
}); | |
describe('can be converted to an array', function() { | |
it('using `Array.from()`', function() { | |
const arr = Array.from(iterable); | |
assert.equal(Array.isArray(arr), true); | |
}); | |
it('where `.length` is still 0', function() { | |
const arr = Array.from(iterable); | |
const length = arr.length; | |
assert.equal(length, 0); | |
}); | |
}); | |
}); | |
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// http://tddbin.com/#?kata=es6/language/iterator/usages | |
// 40: iterator - one example usage. 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 undefined; | |
} | |
get anyLeft() { | |
return this.isEmpty === true; | |
} | |
} | |
describe('Iterator usages', () => { | |
let usersIterable; | |
beforeEach(function(){ | |
const consumableUsers = new ConsumableUsers(); | |
function iteratorFunction() { | |
return { | |
next: function() { | |
return {value: consumableUsers.nextUser, done: consumableUsers.anyLeft} | |
} | |
} | |
} | |
usersIterable = {}; | |
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'); | |
}) | |
}); | |
}); | |
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// http://tddbin.com/#?kata=es6/language/array-api/entries | |
// 41: array - entries | |
// To do: make all tests pass, leave the assert lines unchanged! | |
describe('`[].entries()` returns an iterator object with all entries', function() { | |
it('returns key+value for each element', function() { | |
const arr = ['a', 'b', 'c']; | |
const entriesAsArray = Array.from(arr.entries()); | |
assert.deepEqual(entriesAsArray, [[0,"a"], [1,"b"], [2,"c"]]); | |
}); | |
it('empty elements contain the value `undefined`', function() { | |
const arr = ['one']; | |
arr[2] = 'three'; | |
const secondValue = Array.from(arr.entries())[1]; | |
assert.deepEqual(secondValue, [1, void 0]); | |
}); | |
describe('returns an iterable', function() { | |
it('has `next()` to iterate', function() { | |
const arr = ['one']; | |
const value = arr.entries().next().value; | |
assert.deepEqual(value, [0, 'one']); | |
}); | |
}); | |
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// http://tddbin.com/#?kata=es6/language/array-api/keys | |
// 42: array - `Array.prototype.keys` | |
// To do: make all tests pass, leave the assert lines unchanged! | |
describe('`Array.prototype.keys` returns an iterator for all keys in the array', () => { | |
it('`keys()` returns an iterator', function() { | |
const arr = ['a']; | |
const iterator = arr.keys(); | |
assert.deepEqual(iterator.next(), {value: 0, done: false}); | |
assert.deepEqual(iterator.next(), {value: void 0, done: true}); | |
}); | |
it('gets all keys', function() { | |
const arr = [1, 2, 3]; | |
const keys = Array.from(arr.keys()); | |
assert.deepEqual(keys, [0, 1, 2]); | |
}); | |
it('empty array contains no keys', function() { | |
const arr = []; | |
const keys = [...arr.keys()]; | |
assert.equal(keys.length, 0); | |
}); | |
it('a sparse array without real values has keys though', function() { | |
const arr = [,,]; | |
const keys = [...arr.keys()]; | |
assert.deepEqual(keys, [0, 1]); | |
}); | |
it('also includes holes in sparse arrays', function() { | |
const arr = ['a', , 'c']; | |
const keys = [...arr.keys()]; | |
assert.deepEqual(keys, [0, 1, 2]); | |
}); | |
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// http://tddbin.com/#?kata=es6/language/array-api/values | |
// 43: array - `Array.prototype.values` | |
// To do: make all tests pass, leave the assert lines unchanged! | |
describe('`Array.prototype.values` returns an iterator for all values in the array', () => { | |
it('`values()` returns an iterator', function() { | |
const arr = ['k', 'e', 'y']; | |
const iterator = arr.values(); | |
iterator.next(); | |
iterator.next(); | |
iterator.next(); | |
assert.deepEqual(iterator.next(), {value: void 0, done: true}); | |
}); | |
it('use iterator to drop first key', function() { | |
const arr = ['keys', 'values', 'entries']; | |
const iterator = arr.values(); | |
iterator.next(); | |
assert.deepEqual([...iterator], ['values', 'entries']); | |
}); | |
it('empty array contains no values', function() { | |
const arr = []; | |
const values = [...arr.values()]; | |
assert.equal(values.length, 0); | |
}); | |
it('a sparse array without real values has values though', function() { | |
const arr = [,,]; | |
const keys = [...arr.values()]; | |
assert.deepEqual(keys, [void 0, void 0]); | |
}); | |
it('also includes holes in sparse arrays', function() { | |
const arr = ['a',,'c']; | |
assert.deepEqual([...arr.values()], ['a', void 0, 'c']); | |
}); | |
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// http://tddbin.com/#?kata=es6/language/map/basics | |
// 44: Map - basics | |
// To do: make all tests pass, leave the assert lines unchanged! | |
describe('`Map` is a key/value map', function(){ | |
it('`Map` is a new global constructor function', function() { | |
assert.equal(typeof Map, 'function'); | |
}); | |
it('provides `new Map().set()` to add key+value pair, `get()` to read it by key', function() { | |
let map = new Map().set('key', 'value'); | |
const value = map.get('key'); | |
assert.equal(value, 'value'); | |
}); | |
it('`has()` tells if map has the given key', function() { | |
let map = new Map().set('key', 'value'); | |
const hasIt = map.has('key'); | |
assert.equal(hasIt, true); | |
}); | |
it('a map is iterable', function() { | |
let map = new Map() | |
.set('1', 'one') | |
.set('2', 'two'); | |
const mapAsArray = Array.from(map); // hint: kata #29 http://tddbin.com/#?kata=es6/language/array-api/from | |
assert.deepEqual(mapAsArray, [['1', 'one'], ['2', 'two']]); | |
}); | |
it('complex types can be keys', function() { | |
const otherObj = {x: 1}; | |
let map = new Map().set(otherObj, ''); | |
map.delete(otherObj); | |
assert.equal(map.has(otherObj), false); | |
}); | |
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// http://tddbin.com/#?kata=es6/language/map/get | |
// 45: Map.prototype.get() | |
// To do: make all tests pass, leave the assert lines unchanged! | |
describe('`Map.prototype.get` returns the element from the map for a key', function(){ | |
it('`get(key)` returns the value stored for this key', function() { | |
let map = new Map(); | |
map.set('key', 'value'); | |
const value = map.get('key'); | |
assert.equal(value, 'value'); | |
}); | |
it('multiple calls still return the same value', function() { | |
let map = new Map(); | |
map.set('value', 'value'); | |
var value = map.get(map.get(map.get('value'))); | |
assert.equal(value, 'value'); | |
}); | |
it('requires exactly the value as passed to `set()`', function() { | |
let map = new Map(); | |
const obj = {}; | |
map.set(obj, 'object is key'); | |
assert.equal(map.get(obj), 'object is key'); | |
}); | |
it('leave out the key, and you get the value set for the key `undefined` (void 0)', function() { | |
let map = new Map(); | |
map.set(void 0, 'yo'); | |
const value = map.get(); | |
assert.equal(value, 'yo'); | |
}); | |
it('returns undefined for an unknown key', function() { | |
let map = new Map(); | |
map.set(void 0, 1); | |
const value = map.get('unknown'); | |
assert.equal(value, void 0); | |
}); | |
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// http://tddbin.com/#?kata=es6/language/map/set | |
// 46: Map.prototype.set() | |
// To do: make all tests pass, leave the assert lines unchanged! | |
describe('`Map.prototype.set` adds a new element with key and value to a Map', function(){ | |
it('simplest use case is `set(key, value)` and `get(key)`', function() { | |
let map = new Map().set('key', 'value'); | |
assert.equal(map.get('key'), 'value'); | |
}); | |
it('the key can be a complex type too', function() { | |
const noop = function() {}; | |
let map = new Map().set(noop, 'the real noop'); | |
assert.equal(map.get(noop), 'the real noop'); | |
}); | |
it('calling `set()` again with the same key replaces the value', function() { | |
let map = new Map() | |
.set('key', 'value') | |
.set('key', 'value1'); | |
assert.equal(map.get('key'), 'value1'); | |
}); | |
it('`set()` returns the map object, it`s chainable', function() { | |
let map = new Map() | |
.set(1, 'one') | |
.set(2, 'two') | |
.set(3, 'three'); | |
assert.deepEqual([...map.keys()], [1,2,3]); | |
assert.deepEqual([...map.values()], ['one', 'two', 'three']); | |
}); | |
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// http://tddbin.com/#?kata=es6/language/set/basics | |
// 47: Set - basics | |
// To do: make all tests pass, leave the assert lines unchanged! | |
describe('`Set` lets you store unique values of any type', function(){ | |
it('`Set` is a new global constructor function', function() { | |
assert.equal(typeof Set, 'function'); | |
}); | |
it('every value in a set is unique', function() { | |
let set = new Set(); | |
set.add(1); | |
set.add(2); | |
const expectedSize = 2; | |
assert.equal(set.size, expectedSize); | |
}); | |
it('the string "1" is different to the number 1', function() { | |
let set = new Set(); | |
set.add(1).add('1'); | |
assert.equal(set.size, 2); | |
}); | |
it('even NaN is equal to NaN', function() { | |
let set = new Set(); | |
set.add(NaN); | |
set.add(NaN); | |
assert.equal(set.size, 1); | |
}); | |
it('+0 and -0 are seen as equal', function() { | |
let set = new Set(); | |
set.add(+0); | |
set.add(0); | |
set.add(-0); | |
assert.deepEqual([...set.values()], [+0]); | |
}); | |
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// http://tddbin.com/#?kata=es6/language/set/add | |
// 48: Set - add | |
// To do: make all tests pass, leave the assert lines unchanged! | |
describe('`add()` appends a new element to the end of a Set object.', function(){ | |
let set; | |
beforeEach(() => set = new Set()); | |
it('adds every value, of any type, only ones', function() { | |
const fn = () => {}; | |
set.add(1); | |
set.add(1); | |
set.add(fn); | |
set.add(fn); | |
assert.equal(set.size, 2); | |
}); | |
it('is chainable', function() { | |
set.add(1).add(2); | |
assert.equal(set.has(2), true); | |
}); | |
it('call without params adds undefined', function() { | |
set.add() | |
assert.equal(set.has(void 0), true); | |
}); | |
it('0, -0 and +0 are equal', function() { | |
set.add(0).add(-0).add(+0); | |
assert.equal(set.has(+0), true); | |
}); | |
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// http://tddbin.com/#?kata=es6/language/generator/creation | |
// 49: Generator - creation | |
// To do: make all tests pass, leave the assert lines unchanged! | |
describe('generator can be created in multiple ways', function() { | |
it('the most common way is by adding `*` after `function`', function() { | |
function* g() {} | |
assertIsGenerator(g()); | |
}); | |
it('as a function expression, by adding a `*` after `function`', function() { | |
let g = function*() {}; | |
assertIsGenerator(g()); | |
}); | |
it('inside an object by prefixing the function name with `*`', function() { | |
let obj = { | |
*g() {} | |
}; | |
assertIsGenerator(obj.g()); | |
}); | |
it('computed generator names, are just prefixed with a `*`', function() { | |
const generatorName = 'g'; | |
let obj = { | |
*[generatorName]() {} | |
}; | |
assertIsGenerator(obj.g()); | |
}); | |
it('inside a class the same way', function() { | |
const generatorName = 'g'; | |
class Klazz { | |
*[generatorName]() {} | |
} | |
assertIsGenerator(new Klazz().g()); | |
}); | |
function assertIsGenerator(gen) { | |
const toStringed = '' + gen; | |
assert.equal(toStringed, '[object Generator]'); | |
} | |
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// http://tddbin.com/#?kata=es6/language/generator/iterator | |
// 50: Generator - iterator | |
// To do: make all tests pass, leave the assert lines unchanged! | |
describe('a generator returns an iterable object', function() { | |
function* generatorFunction(){ | |
yield 1; | |
yield 2; | |
} | |
let generator; | |
beforeEach(() => { | |
generator = generatorFunction(); | |
}); | |
it('a generator returns an object', function() { | |
const typeOfTheGenerator = 'object'; | |
assert.equal(typeof generator, typeOfTheGenerator); | |
}); | |
it('a generator object has a key `Symbol.iterator`', function() { | |
const key = Symbol.iterator; | |
assert.equal(key in generator, true); | |
}); | |
it('the `Symbol.iterator` is a function', function() { | |
const theType = typeof generator[Symbol.iterator]; | |
assert.equal(theType, 'function'); | |
}); | |
it('can be looped with `for-of`, which expects an iterable', function() { | |
function iterateForOf(){ | |
for (let value of generator) { | |
// no statements needed | |
} | |
} | |
assert.doesNotThrow(iterateForOf); | |
}); | |
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// http://tddbin.com/#?kata=es6/language/generator/yield | |
// 51: Generator - Yield Expressions | |
// To do: make all tests pass, leave the assert lines unchanged! | |
describe('generator - `yield` is used to pause and resume a generator function', () => { | |
function* generatorFunction() { | |
yield 'hello'; | |
yield 'world'; | |
} | |
let generator; | |
beforeEach(function() { | |
generator = generatorFunction(); | |
}); | |
it('converting a generator to an array resumes the generator until all values are received', () => { | |
let values = Array.from(generator); | |
assert.deepEqual(values, ['hello', 'world']); | |
}); | |
describe('after the first `generator.next()` call', function() { | |
it('the value is "hello"', function() { | |
const {value} = generator.next(); | |
assert.equal(value, 'hello'); | |
}); | |
it('and `done` is false', function() { | |
const {done} = generator.next(); | |
assert.equal(done, false); | |
}); | |
}); | |
describe('after the second `next()` call', function() { | |
let secondItem; | |
let firstItem; | |
beforeEach(function() { | |
firstItem = generator.next(); | |
secondItem = generator.next(); | |
}); | |
it('`value` is "world"', function() { | |
let {value} = secondItem; | |
assert.equal(value, 'world'); | |
}); | |
it('and `done` is still false', function() { | |
const {done} = secondItem; | |
assert.equal(done, false); | |
}); | |
}); | |
describe('after stepping past the last element, calling `next()` that often', function() { | |
it('`done` property equals true, since there is nothing more to iterator over', function() { | |
generator.next(); | |
generator.next(); | |
let {done} = generator.next(); | |
assert.equal(done, true); | |
}); | |
}); | |
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// http://tddbin.com/#?kata=es6/language/generator/send-value | |
// 52: Generator - Send value to a generator | |
// To do: make all tests pass, leave the assert lines unchanged! | |
describe('pass a value to a generator', () => { | |
it('basics: get the values from a generator in two ways', function() { | |
function* generatorFunction() { | |
yield 1; | |
yield 2; | |
} | |
// way #1 | |
var convertedToAnArray = Array.from(generatorFunction()); | |
// way #2 | |
var iterator = generatorFunction(); | |
var iteratedOver = [iterator.next().value, iterator.next().value]; | |
assert.deepEqual(convertedToAnArray, iteratedOver); | |
}); | |
it('pass a value to the iterator', function() { | |
function* generatorFunction() { | |
const param = yield 1; | |
yield param; | |
} | |
var iterator = generatorFunction(); | |
var iteratedOver = [iterator.next().value, iterator.next(2).value]; | |
assert.deepEqual([1, 2], iteratedOver); | |
}); | |
it('a value passed to the 1st `next()` call is ignored', function() { | |
function* generatorFunction() { | |
const param = yield 1; | |
yield param; | |
} | |
let iterator = generatorFunction(); | |
const values = [ | |
iterator.next('irrelevant').value, | |
iterator.next(2).value | |
]; | |
assert.deepEqual(values, [1, 2]); | |
}); | |
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// http://tddbin.com/#?kata=es6/language/map/initialize | |
// 53: Map - initialize | |
// To do: make all tests pass, leave the assert lines unchanged! | |
describe('initialize a `Map`', function(){ | |
it('a `new Map()` is empty, has size=0', function() { | |
const mapSize = new Map().size; | |
assert.equal(mapSize, 0); | |
}); | |
it('init Map with `[[]]` has a size=1', function() { | |
const mapSize = new Map([[]]).size; | |
assert.equal(mapSize, 1); | |
}); | |
it('init a Map with `[[1]]` is the same as `map.set(1, void 0)`', function() { | |
let map1 = new Map([[1]]); | |
let map2 = new Map().set(1, void 0); | |
assertMapsEqual(map1, map2); | |
}); | |
it('init Map with multiple key+value pairs', function() { | |
const pair1 = [1, 'one']; | |
const pair2 = [2, 'two']; | |
const map = new Map([pair1, pair2]); | |
assertMapsEqual(map, new Map().set(...pair1).set(...pair2)); | |
}); | |
it('keys are unique, the last one is used', function() { | |
const pair1 = [1, 'one']; | |
const pair2 = [1, 'uno']; | |
const pair3 = [1, 'eins']; | |
const pair4 = [2, 'two']; | |
const map = new Map([pair1, pair2, pair3, pair4]); | |
assertMapsEqual(map, new Map().set(...pair3).set(...pair4)); | |
}); | |
it('init Map from an Object, is a bit of work', function() { | |
let map = new Map(); | |
const obj = {x: 1, y: 2}; | |
const keys = Object.keys(obj); | |
keys.forEach(key => map.set(key, obj[key])); | |
const expectedEntries = [['x', 1], ['y', 2]]; | |
assertMapsEqual(map, expectedEntries); | |
}); | |
}); | |
function mapToArray(map) { | |
return Array.from(map); | |
} | |
function assertMapsEqual(map1, map2) { | |
assert.deepEqual(mapToArray(map1), mapToArray(map2)); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// http://tddbin.com/#?kata=es6/language/object-api/is | |
// 54: Object - is | |
// To do: make all tests pass, leave the assert lines unchanged! | |
describe('`Object.is()` determines whether two values are the same', function(){ | |
describe('scalar values', function() { | |
it('1 is the same as 1', function() { | |
const areSame = Object.is(1, 1); | |
assert.equal(areSame, true); | |
}); | |
it('int 1 is different to string "1"', function() { | |
const areSame = Object.is(1, '1'); | |
assert.equal(areSame, false); | |
}); | |
it('strings just have to match', function() { | |
const areSame = Object.is('one', 'one'); | |
assert.equal(areSame, true); | |
}); | |
it('+0 is not the same as -0', function() { | |
const areSame = false; | |
assert.equal(Object.is(+0, -0), areSame); | |
}); | |
it('NaN is the same as NaN', function() { | |
const number = NaN; | |
assert.equal(Object.is(NaN, number), true); | |
}); | |
}); | |
describe('coercion, as in `==` and `===`, does NOT apply', function() { | |
it('+0 != -0', function() { | |
const coerced = +0 === -0; | |
const isSame = Object.is(+0, +0); | |
assert.equal(isSame, coerced); | |
}); | |
it('empty string and `false` are not the same', function() { | |
const emptyString = ''; | |
const isSame = Object.is(emptyString, emptyString); | |
assert.equal(isSame, emptyString == false); | |
}); | |
it('NaN', function() { | |
const coerced = NaN != NaN; | |
const isSame = Object.is(NaN, NaN); | |
assert.equal(isSame, coerced); | |
}); | |
it('NaN 0/0', function() { | |
const isSame = Object.is(NaN, 0/0); | |
assert.equal(isSame, true); | |
}); | |
}); | |
describe('complex values', function() { | |
it('`{}` is just not the same as `{}`', function() { | |
const areSame = {} == {}; | |
assert.equal(Object.is({}, {}), areSame); | |
}); | |
it('Map', function() { | |
let map1 = new Map([[1, 'one']]); | |
let map2 = new Map([[1, 'one']]); | |
const areSame = Object.is(map1, map2); | |
assert.equal(areSame, false); | |
}); | |
}); | |
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// http://tddbin.com/#?kata=es6/language/number-api/isinteger | |
// 55: Number - isInteger | |
// To do: make all tests pass, leave the assert lines unchanged! | |
describe('`Number.isInteger()` determines if a value is an integer', function(){ | |
const isTrue = (what) => assert.equal(what, true); | |
const isFalse = (what) => assert.equal(what, false); | |
it('`isInteger` is a static function on `Number`', function() { | |
const whatType = 'function'; | |
assert.equal(typeof Number.isInteger, whatType); | |
}); | |
describe('zero in different ways', function() { | |
it('0 is an integer', function() { | |
const zero = 0; | |
isTrue(Number.isInteger(zero)); | |
}); | |
it('0.000', function() { | |
isTrue(Number.isInteger(0.000)); | |
}); | |
it('the string "0" is NOT an integer', function() { | |
const stringZero = '0'; | |
isFalse(Number.isInteger(stringZero)); | |
}); | |
}); | |
describe('one in different ways', function() { | |
it('0.111 + 0.889', function() { | |
const rest = 0.889; | |
isTrue(Number.isInteger(0.111 + rest)); | |
}); | |
it('0.5 + 0.2 + 0.2 + 0.1 = 1 ... isn`t it?', function() { | |
const oneOrNot = 0.5 + 0.2 + 0.2 + 0.1; | |
isFalse(Number.isInteger(oneOrNot)); | |
}); | |
it('parseInt`ed "1" is an integer', function() { | |
const convertedToInt = Number.parseInt('1.01'); | |
isTrue(Number.isInteger(convertedToInt)); | |
}); | |
}); | |
describe('what is not an integer', function() { | |
it('`Number()` is an integer', function() { | |
const numberOne = Number(1); | |
isTrue(Number.isInteger(numberOne)); | |
}); | |
it('`{}` is NOT an integer', function() { | |
const isit = Number.isInteger({}); | |
isFalse(isit); | |
}); | |
it('`0.1` is not an integer', function() { | |
const isit = Number.isInteger(0.1); | |
isFalse(isit); | |
}); | |
it('`Number.Infinity` is not an integer', function() { | |
const isit = Number.isInteger(Number.Infinity); | |
isFalse(isit); | |
}); | |
it('`NaN` is not an integer', function() { | |
const isit = Number.isInteger(NaN); | |
isFalse(isit); | |
}); | |
}); | |
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// http://tddbin.com/#?kata=es6/language/generator/send-function | |
// 56: Generator - Send function to a generator | |
// To do: make all tests pass, leave the assert lines unchanged! | |
describe('pass a function to a generator', () => { | |
it('the generator can receive a function as a value', function() { | |
const fn = function() {}; | |
function* generatorFunction(fn) { | |
yield; | |
assert.equal(yield null, fn); // remember, don't touch this line | |
} | |
const iterator = generatorFunction(fn); | |
iterator.next(); | |
iterator.next(); | |
}); | |
it('pass a function to the iterator, which calls it', function() { | |
const fn = value => value; | |
function* generatorFunction(fn) { | |
yield fn(1) | |
yield fn(2); | |
} | |
const iterator = generatorFunction(fn); | |
const iteratedOver = [iterator.next().value, iterator.next().value]; | |
assert.deepEqual([1, 2], iteratedOver); | |
}); | |
it('nesting yielded function calls', function() { | |
const fn = function () {}; | |
function* generatorFunction(fn) { | |
yield 1, fn(yield 2, fn(yield 3, fn())); | |
} | |
const iterator = generatorFunction(fn); | |
const iteratedOver = [iterator.next().value, iterator.next().value, iterator.next().value]; | |
assert.deepEqual([1, 2, 3], iteratedOver); | |
}); | |
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// http://tddbin.com/#?kata=es6/language/default-parameters/basics | |
// 57: Default parameters - basics | |
// To do: make all tests pass, leave the assert lines unchanged! | |
describe('default parameters make function parameters more flexible', () => { | |
it('define it using an assignment to the parameter `function(param=1){}`', function() { | |
let number = (int=0) => int; | |
assert.equal(number(), 0); | |
}); | |
it('it is used when undefined is passed', function() { | |
const number = (int = 23) => int; | |
let param; | |
assert.equal(number(param), 23); | |
}); | |
it('it is not used when a value is given', function() { | |
const xhr = (method = 'GET') => method; | |
assert.equal(xhr('POST'), 'POST'); | |
}); | |
it('it is evaluated at run time', function() { | |
let defaultValue = 42; | |
function xhr(method = `value: ${defaultValue}`) { | |
return method; | |
} | |
assert.equal(xhr(), 'value: 42'); | |
}); | |
it('it can also be a function', function() { | |
let defaultValue = () => {}; | |
function fn(value = defaultValue()) { | |
return value; | |
} | |
assert.equal(fn(), defaultValue()); | |
}); | |
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// http://tddbin.com/#?kata=es6/language/reflect/basics | |
// 58: Reflect - basics | |
// To do: make all tests pass, leave the assert lines unchanged! | |
describe('`Reflect` basics', function() { | |
describe('Reflect is special, it is different to e.g. `Object`', function() { | |
it('is not a function', function() { | |
const expectedType = 'object'; | |
assert.equal(typeof Reflect, expectedType); | |
}); | |
it('it can not be instantiated', function() { | |
const tryToConstruct = () => { new Reflect(); }; | |
assert.throws(tryToConstruct, TypeError); | |
}); | |
it('has no `call` method (as opposed to e.g. Object)', function() { | |
const expected = 'undefined'; | |
assert.equal(typeof Reflect.call, expected); | |
}); | |
}); | |
describe('some `Reflect` usages', function() { | |
it('`Reflect.construct()` is like new', function() { | |
let Class = function() {}; | |
assert.equal(Reflect.construct(Class, []) instanceof Class, true); | |
}); | |
it('`Reflect.get()` returns a property`s value', function() { | |
let obj = {x: 23}; | |
assert.equal(Reflect.get(obj, 'x'), 23); | |
}); | |
it('`Reflect.has()` is like `in` just as a function', function() { | |
let obj = {x: 23}; | |
assert.equal(Reflect.has(obj, 'x'), true); | |
}); | |
}); | |
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// http://tddbin.com/#?kata=es6/language/reflect/apply | |
// 59: Reflect - apply | |
// To do: make all tests pass, leave the assert lines unchanged! | |
describe('`Reflect.apply` calls a target function', function() { | |
it('it is a static method', function() { | |
const expectedType = 'function'; | |
assert.equal(typeof Reflect.apply, expectedType) | |
}); | |
it('it calls a callable, e.g. a function', function() { | |
let fn = function() { return 42; }; | |
assert.equal(Reflect.apply(fn, undefined, []), 42); | |
}); | |
it('passing it a non-callable throws a TypeError', function() { | |
let applyOnUncallable = () => { | |
Reflect.apply(Array); | |
}; | |
assert.throws(applyOnUncallable, TypeError); | |
}); | |
it('the second argument is the scope (or the `this`)', function() { | |
class FourtyTwo { | |
constructor() { this.value = 42} | |
fn() {return this.value} | |
} | |
let instance = new FourtyTwo(); | |
const fourtyTwo = Reflect.apply(instance.fn, instance, instance); | |
assert.deepEqual(fourtyTwo, 42); | |
}); | |
it('the 3rd argument is an array of parameters passed to the call', function() { | |
let emptyArrayWithFiveElements = Reflect.apply(Array, undefined, new Array(5)); | |
assert.deepEqual(emptyArrayWithFiveElements.fill(42), [42, 42, 42, 42, 42]); | |
}); | |
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// http://tddbin.com/#?kata=es6/language/reflect/getprototypeof | |
// 60: Reflect - getPrototypeOf | |
// To do: make all tests pass, leave the assert lines unchanged! | |
describe('`Reflect.getPrototypeOf` returns the prototype', function() { | |
it('works like `Object.getPrototypeOf`', function() { | |
const viaObject = Object.getPrototypeOf({}); | |
const viaReflect = Reflect.getPrototypeOf({}); | |
assert.strictEqual(viaObject, viaReflect); | |
}); | |
it('throws a TypeError for a non-object', function() { | |
let fn = () => { Reflect.getPrototypeOf(42) }; | |
assert.throws(fn, TypeError); | |
}); | |
it('a `new Set()` has a prototype', function() { | |
const aSet = new Set(); | |
assert.equal(Reflect.getPrototypeOf(aSet), Set.prototype); | |
}); | |
it('for a class, it is `Klass.prototype`', function() { | |
class Klass {} | |
const proto = Reflect.getPrototypeOf(new Klass()); | |
assert.equal(proto, Klass.prototype); | |
}); | |
it('for a old-style class, works too', function() { | |
function Klass() { } | |
const proto = Reflect.getPrototypeOf(new Klass()); | |
assert.equal(proto, Klass.prototype); | |
}); | |
it('an array has a prototype too', function() { | |
let arr = []; | |
const expectedProto = Array.prototype; | |
assert.equal(Reflect.getPrototypeOf(arr), expectedProto); | |
}); | |
// TODO | |
// it('getting the prototype of an "exotic namespace object" returns `null`', function() { | |
// http://www.ecma-international.org/ecma-262/6.0/#sec-module-namespace-exotic-objects-getprototypeof | |
// Don't know how to write a test for this yet, without creating a dep in tddbin hardcoded | |
// PRs welcome | |
// assert.equal(Reflect.getPrototypeOf(namespace exotic object), null); | |
// }); | |
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// http://tddbin.com/#?kata=es6/language/modules/import | |
// 61: modules - import | |
// To do: make all tests pass, leave the assert lines unchanged! | |
import assert from 'assert'; // is only here for completeness, `assert` is always imported by default | |
import {equal, deepEqual, notEqual} from 'assert'; | |
import {equal as myEqual} from 'assert'; | |
import {default as myAssert} from 'assert'; | |
describe('use `import` to import functions that have been exported (somewhere else)', function() { | |
describe('the import statement', function() { | |
it('is only allowed on the root level', function() { | |
// try to comment this out, it will yell at you :) | |
// import assert from 'assert'; | |
}); | |
it('import an entire module using `import <name> from "<moduleName>"`', function() { | |
// this can't fail, since `assert` is imported by default | |
assert.equal(typeof assert, 'function'); | |
}); | |
}); | |
describe('import members', function() { | |
it('import a single member, using `import {<memberName>} from "module"`', function() { | |
assert.strictEqual(equal, assert.equal); | |
}); | |
describe('separate multiple members with a comma', function() { | |
it('`deepEqual` from the assert module', () => { | |
assert.strictEqual(deepEqual, assert.deepEqual); | |
}); | |
it('`notEqual` from the assert module', () => { | |
assert.strictEqual(notEqual, assert.notEqual); | |
}); | |
}); | |
}); | |
describe('alias imports', function() { | |
it('using `member as alias` as memberName', function() { | |
assert.strictEqual(myEqual, assert.equal); | |
}); | |
it('rename the default export of a module, using `default as alias` as memberName', function() { | |
assert.strictEqual(myAssert, assert); | |
}); | |
}); | |
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// http://tddbin.com/#?kata=es6/language/map/has | |
// 62: Map - `has()` | |
// To do: make all tests pass, leave the assert lines unchanged! | |
describe('`map.has()` indicates whether an element with a key exists', function() { | |
it('finds nothing in an empty map', function() { | |
let map = new Map(); | |
const hasKey = map.has(void 0); | |
assert.equal(hasKey, false); | |
}); | |
it('finds an element by it`s key', function() { | |
let map = new Map([['key', 'VALUE']]); | |
const hasKey = map.has('key'); | |
assert.equal(hasKey, true); | |
}); | |
it('finds `undefined` as key too', function() { | |
let map = new Map([[void 0, 'not defined key']]); | |
const hasUndefinedAsKey = map.has(undefined); | |
assert.equal(hasUndefinedAsKey, true); | |
}); | |
it('does not coerce keys', function() { | |
let map = new Map([['1', 'one']]); | |
const findsStringOne = true; | |
assert.equal(map.has('1'), findsStringOne); | |
}); | |
it('after removal (using `map.delete(<key>)`) it doesnt find the element anymore', function() { | |
let map = new Map([[1, 'one']]); | |
map.delete(1); | |
assert.equal(map.has(1), false); | |
}); | |
it('adding an item (using `map.set(key, value)`) later will make `has()` return true', function() { | |
let map = new Map(); | |
map.set(undefined, 'not defined'); | |
assert.equal(map.has(void 0), true); | |
}); | |
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// http://tddbin.com/#?kata=es6/language/string-api/includes | |
// 63: String - `includes()` | |
// To do: make all tests pass, leave the assert lines unchanged! | |
describe('`string.includes()` finds string within another string', function() { | |
describe('find a single character', function() { | |
it('in a three char string', function() { | |
const searchString = 'x'; | |
assert.equal('xyz'.includes(searchString), true); | |
}); | |
it('reports false if character was not found', function() { | |
const expected = false; | |
assert.equal('xyz'.includes('abc'), expected); | |
}); | |
}); | |
describe('find a string', function() { | |
it('that matches exactly', function() { | |
const findSome = findMe => 'xyz'.includes(findMe); | |
assert.equal(findSome('xyz'), true); | |
}); | |
}); | |
describe('search for an empty string, is always true', function() { | |
it('in an empty string', function() { | |
const emptyString = ''; | |
assert.equal(''.includes(emptyString), true); | |
}); | |
it('in `abc`', function() { | |
const actual = 'abc'.includes(''); | |
assert.equal(actual, true); | |
}); | |
}); | |
describe('special/corner cases', function() { | |
it('search for `undefined` in a string fails', function() { | |
const findInAbc = (what) => 'abc'.includes(what); | |
assert.equal(findInAbc(void 0), false); | |
}); | |
it('searches case-sensitive', function() { | |
const findInAbc = (what) => 'abc'.includes(what); | |
assert.equal(findInAbc('A'), false); | |
}); | |
it('must NOT be a regular expression', function() { | |
const regExp = /a/; | |
assert.throws(() => {''.includes(regExp)}); | |
}); | |
describe('coerces the searched "thing" into a string', function() { | |
it('e.g. from a number', function() { | |
const actual = '123'.includes(3); | |
assert.equal(actual, true); | |
}); | |
it('e.g. from an array', function() { | |
const actual = '123'.includes([1]); | |
assert.equal(actual, true); | |
}); | |
it('e.g. from an object, with a `toString()` method', function() { | |
const objWithToString = {toString: function() {return 1}}; | |
assert.equal('123'.includes(objWithToString), true); | |
}); | |
}); | |
}); | |
describe('takes a position from where to start searching', function() { | |
it('does not find `a` after position 1 in `abc`', function() { | |
const position = 1; | |
assert.equal('abc'.includes('a', position), false); | |
}); | |
it('even the position gets coerced', function() { | |
const findAtPosition = (pos) => 'xyz'.includes('z', pos); | |
assert.equal(findAtPosition('2'), true); | |
}); | |
describe('invalid positions get converted to 0', function() { | |
it('e.g. `undefined`', function() { | |
const findAtPosition = (pos) => 'xyz'.includes('x', pos); | |
assert.equal(findAtPosition(void 0), true); | |
}); | |
it('negative numbers', function() { | |
const findAtPosition = (pos) => 'xyz'.includes('x', pos); | |
assert.equal(findAtPosition(-2), true); | |
}); | |
it('NaN', function() { | |
const findAtPosition = (pos) => 'xyz'.includes('x', pos); | |
assert.equal(findAtPosition(NaN), true); | |
}); | |
}); | |
}); | |
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// http://tddbin.com/#?kata=es6/language/set/delete | |
// 64: Set - delete | |
// To do: make all tests pass, leave the assert lines unchanged! | |
describe('`set.delete()` deletes an element from a set', function(){ | |
let set; | |
beforeEach(() => set = new Set()); | |
describe('use `delete(<value>)` to delete an element', function() { | |
beforeEach(function() { | |
set.add('one').add('two').add('three'); | |
}); | |
it('`delete()` returns `true` when the element was found', function() { | |
const returns = set.delete('one'); | |
assert.strictEqual(returns, true); | |
}); | |
it('and the size decreases', function() { | |
set.delete('one'); | |
assert.equal(set.size, 2); | |
}); | |
}); | |
describe('if nothing was deleted (no element with the given value was found)', function() { | |
it('returns `false`', function() { | |
set.add('one'); | |
const returns = set.delete('two'); | |
assert.equal(returns, false); | |
}); | |
}); | |
describe('`undefined` is a valid value in a set', function() { | |
it('deleting it, when it is not in the set, returns `false` too', function() { | |
let whatToDelete = undefined; | |
assert.equal(set.delete(whatToDelete), false); | |
}); | |
it('`delete()` removes it, when its in the set', function() { | |
set.add(undefined); | |
assert.equal(set.delete(), true); | |
}); | |
}); | |
describe('the value does NOT get casted', function() { | |
it('number 1 is different to string "1"', function() { | |
set.add(1); | |
assert.equal(set.delete('1'), false); | |
}); | |
}); | |
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// http://tddbin.com/#?kata=es6/language/set/api | |
// 65: Set - API overview | |
// To do: make all tests pass, leave the assert lines unchanged! | |
describe('`Set` API overview', function(){ | |
const api = ['size', 'add', 'clear', 'delete', 'entries', 'forEach', 'has', 'keys', 'values']; | |
let set; | |
beforeEach(function() { | |
set = new Set(api); | |
}); | |
it('a Set can be created from an array', function() { | |
let set = new Set(api); | |
assert.deepEqual(Array.from(set), api); | |
}); | |
it('`size` is the number of values', function() { | |
const theSize = set.size; | |
assert.equal(theSize, api.length); | |
}); | |
it('`add()` appends the given value', function() { | |
// hint: to make the example consistent you can add the `Symbol.iterator` to `set` | |
// strongly speaking it is missing in the API. | |
set.add(Symbol.iterator); | |
assert.equal(set.size, api.length + 1); | |
}); | |
it('`clear()` removes all elements', function() { | |
set.clear(); | |
assert.equal(set.size, 0); | |
}); | |
it('`delete()` removes the given value', function() { | |
set.delete('size'); | |
assert.equal(set.size, api.length - 1); | |
}); | |
it('`entries()` returns an iterator for all values', function() { | |
const expectedEntries = api.map(entry => [entry, entry]); | |
const actualEntries = set.entries(); | |
assert.deepEqual([...actualEntries], expectedEntries); | |
}); | |
it('`forEach()` calls a callback for each value', function() { | |
let values = []; | |
set.forEach(value => { values.push(value); }); | |
assert.deepEqual(values, api); | |
}); | |
it('`has()` returns true if the given value is in the set', function() { | |
const propertyName = 'has'; | |
assert.equal(set.has(propertyName), true); | |
}); | |
describe('returns an iterator that contains all values', function() { | |
// in order to be alike to `Map` `keys()` and `values()` are essentially the same thing for a `Set`. | |
it('`keys()`', function() { | |
const allKeys = set.keys(); | |
assert.deepEqual([...allKeys], api); | |
}); | |
it('`values()`', function() { | |
const allValues = set.values(); | |
assert.deepEqual([...allValues], api); | |
}); | |
it('`[Symbol.iterator]()`', function() { | |
const iteratorKey = Symbol.iterator; | |
assert.deepEqual([...set[iteratorKey]()], api); | |
}); | |
}); | |
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// http://tddbin.com/#?kata=es6/language/object-literal/getter | |
// 66: object-literal - getter | |
// To do: make all tests pass, leave the assert lines unchanged! | |
describe('An object literal can also contain getters', () => { | |
it('just prefix the property with `get` (and make it a function)', function() { | |
const obj = { | |
get x() { return 'ax'; } | |
}; | |
assert.equal(obj.x, 'ax'); | |
}); | |
it('must have NO parameters', function() { | |
const obj = { | |
get x() { return 'ax'; } | |
}; | |
assert.equal(obj.x, 'ax'); | |
}); | |
it('can be a computed property (an expression enclosed in `[]`)', function() { | |
const keyName = 'x'; | |
const obj = { | |
get [keyName]() { return 'ax'; } | |
}; | |
assert.equal(obj.x, 'ax'); | |
}); | |
it('can be removed using delete', function() { | |
const obj = { | |
get x() { return 'ax'; } | |
}; | |
delete obj.x; | |
assert.equal(obj.x, void 0); | |
}); | |
// The following dont seem to work in the current transpiler version | |
// but should be correct, as stated here https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/get | |
// It might be corrected later, new knowledge welcome. | |
//it('must not overlap with a pure property', function() { | |
// const obj = { | |
// x: 1, | |
// get x() { return 'ax'; } | |
// }; | |
// | |
// assert.equal(obj.x, 'ax'); | |
//}); | |
// | |
//it('multiple `get` for the same property are not allowed', function() { | |
// const obj = { | |
// x: 1, | |
// get x() { return 'ax'; }, | |
// get x() { return 'ax1'; } | |
// }; | |
// | |
// assert.equal(obj.x, 'ax'); | |
//}); | |
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// http://tddbin.com/#?kata=es6/language/object-literal/setter | |
// 67: object-literal - setter | |
// To do: make all tests pass, leave the assert lines unchanged! | |
describe('An object literal can also contain setters', () => { | |
describe('defining: a setter', function() { | |
it('by prefixing the property with `set` (and make it a function)', function() { | |
let theX = null; | |
const obj = { | |
set x(newX) { theX = newX; } | |
}; | |
obj.x = 'the new X'; | |
assert.equal(theX, 'the new X'); | |
}); | |
it('must have exactly one parameter', function() { | |
let setterCalledWith = void 0; | |
const obj = { | |
set x(foo) { | |
if (arguments.length === 1) { | |
setterCalledWith = arguments[0]; | |
} | |
} | |
}; | |
assert.equal(obj.x = 'new value', setterCalledWith); | |
}); | |
it('can be a computed property (an expression enclosed in `[]`)', function() { | |
const publicPropertyName = 'x'; | |
let privatePropertyName = '_' + publicPropertyName; | |
const obj = { | |
[privatePropertyName]: null, | |
set [publicPropertyName](foo) { | |
this[privatePropertyName] = foo; | |
} | |
}; | |
obj.x = 'axe'; | |
assert.equal(obj._x, 'axe'); | |
}); | |
}); | |
describe('working with/on the setter', function() { | |
it('you can use `delete` to remove the property (including it`s setter)', function() { | |
let setterCalled = false; | |
const obj = { | |
set x(param) { setterCalled = true; } | |
}; | |
// delete the property x here, to make the test pass | |
delete obj.x | |
obj.x = true; | |
assert.equal(setterCalled, false); | |
}); | |
}); | |
// TODO | |
// The following dont seem to work in the current transpiler version | |
// but should be correct, as stated here https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/set | |
// It might be corrected later, new knowledge welcome. | |
// it('must not overlap with a pure property', function() { | |
// const obj = { | |
// x: 1, | |
// set x(val) { return 'ax'; } | |
// }; | |
// assert.equal(obj.x, 'ax'); | |
// }); | |
// it('multiple `set` for the same property are not allowed', function() { | |
// const obj = { | |
// x: 1, | |
// set x(v) { return 'ax'; }, | |
// set x(v) { return 'ax1'; } | |
// }; | |
// assert.equal(obj.x, 'ax'); | |
// }); | |
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// http://tddbin.com/#?kata=es6/language/reflect/construct | |
// 68: Reflect - construct | |
// To do: make all tests pass, leave the assert lines unchanged! | |
describe('`Reflect.construct` is the `new` operator as a function', function() { | |
describe('the function itself', function() { | |
it('is static on the `Reflect` object', function() { | |
const name = 'constructor'; | |
assert.equal(name in Reflect, true); | |
}); | |
it('is of type `function`', function() { | |
const expectedType = 'function'; | |
assert.equal(typeof Reflect.construct, expectedType) | |
}); | |
}); | |
describe('the 1st parameter is the constructor to be invoked', function() { | |
it('fails when given a number as constructor', function() { | |
let aNumber = 42; | |
assert.throws(() => { Reflect.construct(aNumber, []) }, TypeError); | |
}); | |
it('works giving a function', function() { | |
let aFunction = () => {}; | |
assert.doesNotThrow(() => { Reflect.construct(aFunction, []) }); | |
}); | |
it('works giving a class', function() { | |
const aClass = class {}; | |
assert.doesNotThrow(() => { Reflect.construct(aClass, []) }); | |
}); | |
}); | |
describe('the 2nd parameter is a list of arguments, that will be passed to the constructor', function() { | |
const aClass = class {}; | |
it('fails when it`s not an array(-like), e.g. a number', function() { | |
let aNumber = 42; | |
assert.throws(() => { Reflect.construct(aClass, aNumber) }, TypeError); | |
}); | |
it('works with an array-like object (the `length` property look up should not throw)', function() { | |
let arrayLike = {get length() { [].length; }}; | |
assert.doesNotThrow(() => { Reflect.construct(aClass, arrayLike) }); | |
}); | |
it('works with a real array', function() { | |
let realArray = ['foo', 'bar']; | |
assert.doesNotThrow(() => { Reflect.construct(aClass, realArray) }); | |
}); | |
}); | |
describe('in use', function() { | |
it('giving it a class it returns an instance of this class', function() { | |
class Constructable {} | |
let instance = Reflect.construct(Constructable, []); // use Reflect.construct here!!! | |
assert.equal(instance instanceof Constructable, true); | |
}); | |
describe('the list of arguments are passed to the constructor as given', function() { | |
class Constructable { | |
constructor(...args) { this.args = args; } | |
} | |
it('if none given, nothing is passed', function() { | |
let instance = Reflect.construct(Constructable, []); | |
assert.deepEqual(instance.args, []); | |
}); | |
it('passing an array, all args of any type are passed', function() { | |
const argumentsList = ['arg1', ['arg2.1', 'arg2.2'], {arg: 3}]; | |
let instance = Reflect.construct(Constructable, argumentsList); | |
assert.deepEqual(instance.args, argumentsList); | |
}); | |
}); | |
}); | |
describe('the length property', function() { | |
it('of `Reflect.construct` is 2', function() { | |
let expected = 2; | |
assert.equal(Reflect.construct.length, expected); | |
}); | |
}); | |
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// http://tddbin.com/#?kata=es6/language/reflect/defineproperty | |
// 69: Reflect - defineProperty | |
// To do: make all tests pass, leave the assert lines unchanged! | |
describe('`Reflect.defineProperty()` is like `Object.defineProperty()` but returns a Boolean.', function() { | |
describe('the function itself', function() { | |
it('is static on the `Reflect` object', function() { | |
const name = 'defineProperty'; | |
assert.equal(name in Reflect, true); | |
}); | |
it('is of type `function`', function() { | |
const expectedType = 'function'; | |
assert.equal(typeof Reflect.defineProperty, expectedType) | |
}); | |
}); | |
describe('the 1st parameter is the object on which to define a property', function() { | |
it('fails if it is not an object', function() { | |
let noObj = ''; | |
assert.throws(() => { Reflect.defineProperty(noObj, 'x', {value: 42}); }, TypeError); | |
}); | |
it('accepts an object', function() { | |
let obj = {}; | |
assert.doesNotThrow(() => { Reflect.defineProperty(obj, 'x', {value: 42}); }); | |
}); | |
it('accepts an instance (of a class)', function() { | |
class Foo {} | |
let instance = new Foo(); | |
assert.doesNotThrow(() => { Reflect.defineProperty(instance, 'x', {value: 42}); }); | |
}); | |
}); | |
describe('2nd parameter is the name of the property to be defined on the object (normally a string)', function() { | |
it('works with a `normal` string', function() { | |
let obj = {}; | |
Reflect.defineProperty(obj, 'prop', {}); | |
assert.equal('prop' in obj, true); | |
}); | |
it('a number gets converted into a string', function() { | |
let obj = {}; | |
Reflect.defineProperty(obj, 1, {}); | |
assert.equal('1' in obj, true); | |
}); | |
it('`undefined` also gets converted into a string (watch out!)', function() { | |
let obj = {}; | |
let undef; | |
Reflect.defineProperty(obj, undef, {}); | |
assert.equal('undefined' in obj, true); | |
}); | |
it('it can be a symbol', function() { | |
let obj = {}; | |
const sym = Symbol.for('prop'); | |
Reflect.defineProperty(obj, sym, {}); | |
assert.equal(sym in obj, true); | |
}); | |
}); | |
describe('the `value` is part of the 3rd parameter, given as a property in an object `{value: ...}`', function() { | |
// The entire complexity of the 3rd parameter might be covered in a later kata. | |
it('contains the initial value of the property, as an object in the property `value`', function() { | |
let obj = {}; | |
Reflect.defineProperty(obj, 'prop', {value: 'property value'}); | |
assert.equal(obj.prop, 'property value'); | |
}); | |
it('can be of any type (even itself)', function() { | |
let obj = {}; | |
Reflect.defineProperty(obj, 'prop', {value: obj}); | |
assert.equal(obj.prop, obj); | |
}); | |
}); | |
describe('the return value of the function indicates wether the property was defined successfully', function() { | |
describe('returns true', function() { | |
it('when the property was created (which requires the 3rd parameter too!!!)', function() { | |
let instance = new class {}; | |
const wasPropertyDefined = Reflect.defineProperty(instance, 'prop', {value: 'value'}); | |
assert.equal(wasPropertyDefined, true); | |
}); | |
it('no matter what the value of the property is (just the 3rd param has to exist as `{}`)', function() { | |
let instance = new class {}; | |
const wasPropertyDefined = Reflect.defineProperty(instance, 'prop', {}); | |
assert.equal(wasPropertyDefined, true); | |
}); | |
}); | |
describe('returns false', function() { | |
it('when no property name is given (since no property has been added)', function() { | |
let instance = new class {}; | |
const wasPropertyDefined = Reflect.defineProperty(instance, null, {}); | |
assert.equal(wasPropertyDefined, false); | |
}); | |
it('when no 3rd parameter, the descriptor is given', function() { | |
let instance = new class {}; | |
const wasPropertyDefined = Reflect.defineProperty(instance, 'prop'); | |
assert.equal(wasPropertyDefined, false); | |
}); | |
}); | |
}); | |
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// http://tddbin.com/#?kata=es6/language/set/clear | |
// 70: Set - clear | |
// To do: make all tests pass, leave the assert lines unchanged! | |
describe('`clear()` removes all elements from a Set object.', function(){ | |
let set; | |
beforeEach(() => set = new Set()); | |
it('`set.size` becomes 0', function() { | |
set.add('one').add(2); | |
set.clear(); | |
var expectedSize = 0; | |
assert.equal(set.size, expectedSize); | |
}); | |
it('the iterator `set.entries()` will not contain any items', function() { | |
set.add('one').add(2); | |
set.clear(); | |
const {done} = set.entries().next(); | |
assert.equal(done, true); | |
}); | |
it('any call to `set.has()` returns false', function() { | |
set.add('one').add(2); | |
set.clear(); | |
assert.deepEqual(set.has(2), false); | |
}); | |
it('returns `undefined`', function() { | |
var expectedReturn; | |
assert.equal(set.clear(), expectedReturn); | |
}); | |
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// http://tddbin.com/#?kata=es6/language/string-api/repeat | |
// 71: String - `repeat()` | |
// To do: make all tests pass, leave the assert lines unchanged! | |
describe('`str.repeat(x)` appends `x` copies of `str` to each other and returns it', function() { | |
describe('pass the count to `str.repeat(count)`', function() { | |
it('for `1` the string stays the same', function() { | |
const what = 'one'.repeat(1); | |
assert.equal(what, 'one'); | |
}); | |
it('for `3` the string `x` becomes `xxx`', function() { | |
const actual = 'x'.repeat(3); | |
assert.equal(actual, 'xxx'); | |
}); | |
it('for `0` an empty string is returned', function() { | |
const dontRepeat = '1'.repeat(0); | |
assert.equal('shrink'.repeat(dontRepeat), ''); | |
}); | |
it('the count is not an int, such as "3", it gets coerced to an int', function() { | |
const repeated = 'three'.repeat('3'); | |
assert.equal(repeated, 'threethreethree'); | |
}); | |
}); | |
describe('throws an error for', function() { | |
it('a count of <0', function() { | |
const belowZero = -1; | |
assert.throws(() => { ''.repeat(belowZero); }, RangeError); | |
}); | |
it('a count of +Infinty', function() { | |
let infinity = Infinity; | |
assert.throws(() => { ''.repeat(infinity); }, RangeError); | |
}); | |
}); | |
describe('accepts everything that can be coerced to a string', function() { | |
it('e.g. a boolean', function() { | |
let aBool = false; | |
assert.equal(String.prototype.repeat.call(aBool, 2), 'falsefalse'); | |
}); | |
it('e.g. a number', function() { | |
let aNumber = 1; | |
assert.equal(String.prototype.repeat.call(aNumber, 2), '11'); | |
}); | |
}); | |
describe('for my own (string) class', function() { | |
it('calls `toString()` to make it a string', function() { | |
class MyString { toString() { return 'my string'; } } | |
const expectedString = new MyString(); | |
assert.equal(String(new MyString()).repeat(1), expectedString); | |
}); | |
it('`toString()` is only called once', function() { | |
let counter = 1; | |
class X { | |
toString() { | |
return counter++; | |
} | |
} | |
let repeated = String(new X()).repeat(2); | |
assert.equal(repeated, '11'); | |
}); | |
}); | |
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// http://tddbin.com/#?kata=es6/language/string-api/startswith | |
// 72: String - `startsWith()` | |
// To do: make all tests pass, leave the assert lines unchanged! | |
describe('`str.startsWith(searchString)` determines whether `str` begins with `searchString`.', function() { | |
const s = 'the string s'; | |
describe('1st parameter, the string to search for', function() { | |
it('works with just a character', function() { | |
const actual = s.startsWith('t'); | |
assert.equal(actual, true); | |
}); | |
it('works with a string', function() { | |
const expected = true; | |
assert.equal(s.startsWith('the'), expected); | |
}); | |
it('works with unicode characters', function() { | |
const nuclear = '☢ NO'; | |
assert.equal(nuclear.startsWith('☢'), true); | |
}); | |
it('a regular expression throws a TypeError', function() { | |
const aRegExp = /the/; | |
assert.throws(() => {''.startsWith(aRegExp)}, TypeError); | |
}); | |
}); | |
describe('2nd parameter, the position where to start searching from', function() { | |
it('find "str" at position 4', function() { | |
const position = 4; | |
assert.equal(s.startsWith('str', position), true); | |
}); | |
it('`undefined` is the same as 0', function() { | |
let _undefined_; | |
assert.equal(s.startsWith('the', _undefined_), true); | |
}); | |
it('the parameter gets coerced to an int', function() { | |
const position = '4'; | |
assert.equal(s.startsWith('str', position), true); | |
}); | |
it('a value larger than the string`s length, returns false', function() { | |
const expected = false; | |
assert.equal(s.startsWith(' ', s.length + 1), expected); | |
}); | |
}); | |
describe('transfer the functionality to other objects', function() { | |
const startsWith = (...args) => String.prototype.startsWith.call(...args); | |
it('e.g. a boolean', function() { | |
let aBool = true; | |
assert.equal(startsWith(!aBool, 'false'), true); | |
}); | |
it('e.g. a number', function() { | |
let aNumber = 1900; | |
assert.equal(startsWith(aNumber + 84, '1984'), true); | |
}); | |
it('also using the position works', function() { | |
const position = 1; | |
assert.equal(startsWith(1994, '99', position), true); | |
}); | |
}); | |
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// http://tddbin.com/#?kata=es6/language/generator/return | |
// 73: Generator - `return` inside a generator is special | |
// To do: make all tests pass, leave the assert lines unchanged! | |
describe('`return` in a generator function is special', function() { | |
describe('the returned value is an IteratorResult (just like any value returned via `yield`)', function() { | |
it('returns an IteratorResult (an object with the properties `value` and `done`)', function() { | |
function* generatorFunction() { return 1; } | |
const returned = generatorFunction().next(); | |
const propertyNames = ['value', 'done']; | |
assert.deepEqual(Object.keys(returned), propertyNames); | |
}); | |
it('the property `value` is the value given after the `return` statement', function() { | |
function* generatorFunction() { return 23; } | |
const {value} = generatorFunction().next(); | |
assert.equal(value, 23); | |
}); | |
it('the property `done` is true', function() { | |
function* generatorFunction() { return 42; } | |
const {done} = generatorFunction().next(); | |
assert.equal(done, true); | |
}); | |
it('NOTE: `yield` does not return `done=true` but `done=false`!', function() { | |
function* generatorFunction() { yield 1; } | |
const returned = generatorFunction().next(); | |
assert.deepEqual(returned, {value: 1, done: false}); | |
}); | |
it('a missing `return` returns {value: undefined, done: true}', function() { | |
function* generatorFunction() { } | |
const returned = generatorFunction().next(); | |
assert.deepEqual(returned, {value: void 0, done: true}); | |
}); | |
}); | |
describe('mixing `return` and `yield`', function() { | |
function* generatorFunctionWithYieldAndReturn() { | |
yield 1; | |
return 2; | |
} | |
it('is possible', function() { | |
const iterator = generatorFunctionWithYieldAndReturn(); | |
const values = [ | |
iterator.next(), | |
iterator.next() | |
]; | |
assert.deepEqual(values, [{value: 1, done: false}, {value: 2, done: true}]); | |
}); | |
it('the mix behaves different to two `yield`s', function() { | |
const iterator = generatorFunctionWithYieldAndReturn(); | |
const values = [1]; | |
assert.deepEqual(Array.from(iterator), values); | |
}); | |
it('two `yield`s returning values', function() { | |
function* generatorFunctionWithTwoYields() { | |
yield 1; | |
yield 2; | |
} | |
assert.deepEqual(Array.from(generatorFunctionWithTwoYields()), [1, 2]); | |
}); | |
it('returning a yielded value', function() { | |
function* generatorFunction() { | |
yield 1; | |
yield 2; | |
} | |
const iterator = generatorFunction(); | |
const values = [ | |
iterator.next().value, | |
iterator.next(2).value | |
]; | |
assert.deepEqual(values, [1, 2]); | |
}); | |
}); | |
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// http://tddbin.com/#?kata=es6/language/string-api/endswith | |
// 74: String - `endsWith()` | |
// To do: make all tests pass, leave the assert lines unchanged! | |
describe('`str.endsWith(searchString)` determines whether `str` ends with `searchString`.', function() { | |
const s = 'el fin'; | |
describe('1st parameter, the string to search for', function() { | |
it('works with just a character', function() { | |
const doesEndWith = s.endsWith('n'); | |
assert.equal(doesEndWith, true); | |
}); | |
it('works with a string', function() { | |
const expected = true; | |
assert.equal(s.endsWith('fin'), expected); | |
}); | |
it('works with unicode characters', function() { | |
const nuclear = 'NO ☢'; | |
assert.equal(nuclear.endsWith('☢'), true); | |
}); | |
it('a regular expression throws a TypeError', function() { | |
const aRegExp = /the/; | |
assert.throws(() => {''.endsWith(aRegExp)}, TypeError); | |
}); | |
}); | |
describe('2nd parameter, searches within this string as if this string were only this long', function() { | |
it('find "el" at a substring of the length 2', function() { | |
const endPos = 2; | |
assert.equal(s.endsWith('el', endPos), true); | |
}); | |
it('`undefined` uses the entire string', function() { | |
let _undefined_; | |
assert.equal(s.endsWith('fin', _undefined_), true); | |
}); | |
it('the parameter gets coerced to an int', function() { | |
const position = '5'; | |
assert.equal(s.endsWith('fi', position), true); | |
}); | |
describe('value less than 0', function() { | |
it('returns `true`, when searching for an empty string', function() { | |
const emptyString = ''; | |
assert.equal('1'.endsWith(emptyString, -1), true); | |
}); | |
it('return `false`, when searching for a non-empty string', function() { | |
const notEmpty = 'huh'; | |
assert.equal('1'.endsWith(notEmpty, -1), false); | |
}); | |
}); | |
}); | |
describe('transfer the functionality to other objects', function() { | |
const endsWith = (...args) => String.prototype.endsWith.call(...args); | |
it('e.g. a boolean', function() { | |
let aBool = true; | |
assert.equal(endsWith(!aBool, 'lse'), true); | |
}); | |
it('e.g. a number', function() { | |
let aNumber = 84; | |
assert.equal(endsWith(aNumber + 1900, 84), true); | |
}); | |
it('also using the position works', function() { | |
const position = 3; | |
assert.equal(endsWith(1994, '99', position), true); | |
}); | |
}); | |
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// http://tddbin.com/#?kata=es6/language/promise/basics | |
// 75: Promise - basics | |
// To do: make all tests pass, leave the assert lines unchanged! | |
describe('a Promise represents an operation that hasn`t completed yet, but is expected in the future', function() { | |
it('`Promise` is a global function', function() { | |
const expectedType = 'function'; | |
assert.equal(typeof Promise, expectedType); | |
}); | |
describe('the constructor', function() { | |
it('instantiating it without params throws', function() { | |
const fn = () => { new Promise(); } | |
assert.throws(fn); | |
}); | |
it('expects a function as parameter', function() { | |
const param = function () {}; | |
assert.doesNotThrow(() => { new Promise(param); }); | |
}); | |
}); | |
describe('simplest promises', function() { | |
it('resolve a promise by calling the `resolve` function given as first parameter', function(done) { | |
let promise = new Promise((resolve) => { | |
resolve(); | |
}); | |
promise | |
.then(() => done()) | |
.catch(() => done(new Error('The promise is expected to resolve.'))); | |
}); | |
it('the `resolve` function can return a value, that is consumed by the `promise.then()` callback', function(done) { | |
let promise = new Promise((resolve) => { | |
resolve(42); | |
}); | |
promise | |
.then(value => {assert.equal(value, 42); done(); }) | |
.catch(() => done(new Error('The promise is expected to resolve with 42!'))); | |
}); | |
it('rejecting a promise is done by calling the callback given as 2nd parameter', function(done) { | |
let promise = new Promise((resolve, reject) => { | |
reject(); | |
}); | |
promise | |
.then(() => done(new Error('The promise is expected to be rejected.'))) | |
.catch(() => done()); | |
}); | |
}); | |
describe('an asynchronous promise', function() { | |
it('can resolve later, also by calling the first callback', function(done) { | |
let promise = new Promise((resolve) => { | |
setTimeout(() => resolve(), 100); | |
}); | |
promise | |
.then(() => done()) | |
.catch(() => done(new Error('The promise is expected to resolve.'))); | |
}); | |
it('reject it at some later point in time, calling the 2nd callback', function(done) { | |
let promise = new Promise((resolve, reject) => { | |
setTimeout(() => reject(), 100); | |
}); | |
promise | |
.then(() => done(new Error('The promise is expected to be rejected.'))) | |
.catch(() => done()); | |
}); | |
}); | |
describe('test library (mocha here) support for promises', function() { | |
it('just returning the promise makes the test library check that the promise resolves', function() { | |
let promise = new Promise((resolve, reject) => { | |
resolve(); | |
}); | |
// return the promise to mocha, it has the checking for promise resolving built in, when it receives a promise | |
return promise; | |
}); | |
}); | |
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// http://tddbin.com/#?kata=es6/language/promise/creation | |
// 76: Promise - creation | |
// To do: make all tests pass, leave the assert lines unchanged! | |
describe('a promise can be created in multiple ways', function() { | |
describe('creating a promise fails when', function() { | |
it('using `Promise` as a function', function() { | |
function callPromiseAsFunction() { | |
new Promise(); | |
} | |
assert.throws(callPromiseAsFunction); | |
}); | |
it('no parameter is passed', function() { | |
function promiseWithoutParams() { | |
new Promise(); | |
} | |
assert.throws(promiseWithoutParams); | |
}); | |
it('passing a non-callable throws too', function() { | |
const notAFunction = null; | |
assert.throws(() => { new Promise(notAFunction); }); | |
}); | |
}); | |
describe('most commonly Promises get created using the constructor', function() { | |
it('by passing a resolve function to it', function() { | |
const promise = new Promise((resolve) => resolve()); | |
return promise; | |
}); | |
it('by passing a resolve and a reject function to it', function(done) { | |
const promise = new Promise((resolve, reject) => reject()); | |
promise | |
.then(() => done(new Error('Expected promise to be rejected.'))) | |
.catch(done); | |
}); | |
}); | |
describe('extending a `Promise`', function() { | |
it('using `class X extends Promise{}` is possible', function() { | |
class MyPromise extends Promise {} | |
const curpromise = new MyPromise(resolve => resolve()); | |
curpromise | |
.then(() => done()) | |
.catch(e => done(new Error('Expected to resolve, but failed with: ' + e))); | |
}); | |
it('must call `super()` in the constructor if it wants to inherit/specialize the behavior', function() { | |
class ResolvingPromise extends Promise { | |
constructor() { | |
super(); | |
} | |
} | |
return new ResolvingPromise(); | |
}); | |
}); | |
describe('`Promise.all()` returns a promise that resolves when all given promises resolve', function() { | |
it('returns all results', function(done) { | |
const promise = Promise.all([ | |
new Promise(resolve => resolve(1)), | |
new Promise(resolve => resolve(2)) | |
]); | |
promise | |
.then(value => { assert.deepEqual(value, [1, 2]); done(); }) | |
.catch(e => done(new Error(e))); | |
}); | |
it('is rejected if one rejects', function(done) { | |
const promise = Promise.all([ | |
new Promise(resolve => reject(1)), | |
new Promise(resolve => resolve(2)) | |
]); | |
promise | |
.then(() => done(new NotRejectedError())) | |
.catch(() => done()); | |
}); | |
}); | |
describe('`Promise.race()` returns the first settled promise', function() { | |
it('if it resolves first, the promises resolves', function(done) { | |
const lateRejectedPromise = new Promise((resolve, reject) => setTimeout(reject, 100)); | |
const earlyResolvingPromise = new Promise(resolve => resolve('1st :)')); | |
const promise = Promise.race([earlyResolvingPromise, lateRejectedPromise]); | |
promise | |
.then(value => { assert.deepEqual(value, '1st :)'); done(); }) | |
.catch(e => done(new Error('Expected to resolve, but failed with: ' + e))); | |
}); | |
it('if one of the given promises rejects first, the returned promise is rejected', function(done) { | |
const earlyRejectedPromise = new Promise((resolve, reject) => reject('I am a rejector')); | |
const lateResolvingPromise = new Promise(resolve => setTimeout(resolve, 10)); | |
const promise = Promise.race([earlyRejectedPromise, lateResolvingPromise]); | |
promise | |
.then(() => done(new NotRejectedError())) | |
.catch(value => { assert.equal(value, 'I am a rejector'); done(); }) | |
.catch(done); | |
}); | |
}); | |
describe('`Promise.resolve()` returns a resolving promise', function() { | |
it('if no value given, it resolves with `undefined`', function(done) { | |
const promise = Promise.resolve(); | |
promise | |
.then(value => { assert.deepEqual(value, void 0); done(); }) | |
.catch(e => done(new Error('Expected to resolve, but failed with: ' + e))); | |
}); | |
it('resolves with the given value', function(done) { | |
const promise = Promise.resolve('quick resolve'); | |
promise | |
.then(value => { assert.equal(value, 'quick resolve'); done(); }) | |
.catch(e => done(e)); | |
}); | |
}); | |
describe('`Promise.reject()` returns a rejecting promise', function() { | |
it('if no value given, it rejects with `undefined`', function(done) { | |
const promise = Promise.reject(); | |
promise | |
.then(() => done(new NotRejectedError())) | |
.catch(value => { assert.deepEqual(value, void 0); done(); }) | |
.catch(done); | |
}); | |
it('the parameter passed to `reject()` can be used in the `.catch()`', function(done) { | |
const promise = Promise.reject('quick reject'); | |
promise | |
.then(() => done(new NotRejectedError())) | |
.catch(value => { assert.deepEqual(value, 'quick reject'); done(); }) | |
.catch(done); | |
}); | |
}); | |
}); | |
class NotRejectedError extends Error { | |
constructor() { | |
super(); | |
this.message = 'Expected promise to be rejected.'; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// http://tddbin.com/#?kata=es6/language/promise/chaining-then | |
// 77: Promise - chaining | |
// To do: make all tests pass, leave the assert lines unchanged! | |
describe('chaining multiple promises can enhance readability', () => { | |
describe('prerequisites for understanding', function() { | |
it('reminder: the test passes when a fulfilled promise is returned', function() { | |
return Promise.resolve('I should fulfill.'); | |
}); | |
it('a function given to `then()` fulfills (if it doesnt throw)', function() { | |
const beNice = () => 'I am nice'; | |
return Promise.resolve() | |
.then(beNice) | |
.then(niceMessage => assert.equal(niceMessage, 'I am nice')); | |
}); | |
}); | |
describe('chain promises', function() { | |
const removeMultipleSpaces = string => string.replace(/\s+/g, ' '); | |
it('`then()` receives the result of the promise it was called on', function() { | |
const wordsPromise = Promise.resolve('one space between each word'); | |
wordsPromise | |
.then(string => removeMultipleSpaces()) | |
.then(actual => {assert.equal(actual, 'one space between each word')}) | |
; | |
}); | |
const appendPeriod = string => `${string}.`; | |
it('multiple `then()`s can be chained', function() { | |
const wordsPromise = Promise.resolve('Sentence without an end'); | |
wordsPromise | |
.then(removeMultipleSpaces) | |
.then(appendPeriod) | |
.then(actual => {assert.equal(actual, 'Sentence without an end.')}) | |
; | |
}); | |
const trim = string => string.replace(/^\s+/, '').replace(/\s+$/, ''); | |
it('order of the `then()`s matters', function() { | |
const wordsPromise = Promise.resolve('Sentence without an end '); | |
return wordsPromise | |
.then(removeMultipleSpaces) | |
.then(trim) | |
.then(appendPeriod) | |
.then(actual => {assert.equal(actual, 'Sentence without an end.')}) | |
; | |
}); | |
const asyncUpperCaseStart = (string, onDone) => { | |
const format = onDone(string[0].toUpperCase() + string.substr(1)); | |
setTimeout(format, 10); | |
}; | |
it('any of the things given to `then()` can resolve asynchronously (the real power of Promises)', function() { | |
const wordsPromise = Promise.resolve('sentence without an end'); | |
wordsPromise | |
.then(string => new Promise(resolve => asyncUpperCaseStart)) | |
.then(string => new Promise(resolve => setTimeout(() => resolve(appendPeriod(string)), 100))) | |
.then(actual => {assert.equal(actual, 'Sentence without an end.')}) | |
; | |
}); | |
it('also asynchronously, the order still matters, promises wait, but don`t block', function() { | |
const wordsPromise = Promise.resolve('trailing space '); | |
wordsPromise | |
.then(string => new Promise(resolve => setTimeout(() => resolve(trim(string)), 100))) | |
.then(string => new Promise(resolve => asyncUpperCaseStart(string, resolve))) | |
.then(string => new Promise(resolve => setTimeout(() => resolve(appendPeriod(string)), 100))) | |
.then(actual => {assert.equal(actual, 'Trailing space.')}) | |
; | |
}); | |
}); | |
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// http://tddbin.com/#?kata=es6/language/promise/api | |
// 78: Promise - API overview | |
// To do: make all tests pass, leave the assert lines unchanged! | |
describe('`Promise` API overview', function() { | |
it('`new Promise()` requires a function as param', () => { | |
const param = (resolve) => resolve(); | |
assert.doesNotThrow(() => { new Promise(param); }); | |
}); | |
describe('resolving a promise', () => { | |
// reminder: the test passes when a fulfilled promise is returned | |
it('via constructor parameter `new Promise((resolve) => { resolve(); })`', () => { | |
const param = (resolve) => { resolve(); }; | |
return new Promise(param); | |
}); | |
it('using `Promise.resolve()`', () => { | |
return Promise.resolve('all fine'); | |
}); | |
}); | |
describe('a rejected promise', () => { | |
it('using the constructor parameter', (done) => { | |
const promise = new Promise((resolve, reject) => reject()); | |
promise | |
.then(() => done(new Error('The promise is expected to be rejected.'))) | |
.catch(() => done()); | |
}); | |
it('via `Promise.reject()`', (done) => { | |
const promise = Promise.reject(); | |
promise | |
.then(() => done(new Error('The promise is expected to be rejected.'))) | |
.catch(() => done()); | |
}); | |
}); | |
const resolvingPromise = Promise.resolve(); | |
const rejectingPromise = Promise.reject(); | |
describe('`Promise.all()`', () => { | |
it('`Promise.all([p1, p2])` resolves when all promises resolve', () => | |
Promise.all([resolvingPromise, resolvingPromise]) | |
); | |
it('`Promise.all([p1, p2])` rejects when a promise is rejected', (done) => { | |
Promise.all([resolvingPromise, rejectingPromise]) | |
.then(() => done(new Error('The promise is expected to be rejected.'))) | |
.catch(() => done()) | |
}); | |
}); | |
describe('`Promise.race()`', () => { | |
it('`Promise.race([p1, p2])` resolves when one of the promises resolves', () => | |
Promise.race([resolvingPromise, rejectingPromise]) | |
); | |
it('`Promise.race([p1, p2])` rejects when one of the promises rejects', (done) => { | |
Promise.race(rejectingPromise, [resolvingPromise]) | |
.then(() => done(new Error('The promise is expected to be rejected.'))) | |
.catch(() => done()) | |
}); | |
it('`Promise.race([p1, p2])` order matters (and timing)', () => | |
Promise.race([resolvingPromise, rejectingPromise]) | |
); | |
}); | |
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// http://tddbin.com/#?kata=es6/language/promise/catch | |
// 79: Promise - catch | |
// To do: make all tests pass, leave the assert lines unchanged! | |
// Here we use promises to trigger, don't modify the block with the | |
// returning promise! | |
describe('`catch()` returns a Promise and deals with rejected cases only', () => { | |
describe('prerequisites for understanding', () => { | |
it('*return* a fulfilled promise, to pass a test', () => { | |
return Promise.resolve(); | |
assert(false); // Don't touch! Make the test pass in the line above! | |
}); | |
it('reminder: the test passes when a fulfilled promise is returned', () => { | |
return Promise.resolve('I should fulfill.'); | |
}); | |
}); | |
describe('`catch` method basics', () => { | |
it('is an instance method', () => { | |
const p = Promise.reject(); | |
assert.equal(typeof p.catch, 'function'); | |
}); | |
it('catches only promise rejections', (done) => { | |
const promise = Promise.reject(); | |
promise | |
.then(() => { done('Should not be called!'); }) | |
.catch(done); | |
}); | |
it('returns a new promise', () => { | |
const whatToReturn = () => Promise.reject(); | |
const promise = Promise.reject(); | |
return promise.catch(() => | |
whatToReturn | |
); | |
}); | |
it('converts it`s return value into a promise', () => { | |
const p = Promise.reject(); | |
const p1 = p.catch(() => 'promise?'); | |
return p1.then(result => assert.equal('promise?', result)); | |
}); | |
it('the first parameter is the rejection reason', () => { | |
const p = Promise.reject('oops'); | |
return p.catch(reason => { | |
assert.equal(reason, 'oops'); | |
}); | |
}); | |
}); | |
describe('multiple `catch`es', () => { | |
it('only the first `catch` is called', () => { | |
const p = Promise.reject('1'); | |
const p1 = p | |
.catch(reason => `${reason} AND 2`) | |
.catch(reason => `${reason} AND FOO`) | |
; | |
return p1.then(result => | |
assert.equal(result, '1 AND 2') | |
); | |
}); | |
it('if a `catch` throws, the next `catch` catches it', () => { | |
const p = Promise.reject('1'); | |
const p1 = p | |
.catch(reason => { throw Error(`${reason} AND 2`) }) | |
.catch(err => { throw Error(`${err.message} AND 3`) }) | |
.catch(err => err.message) | |
; | |
return p1.then(result => | |
assert.equal(result, '1 AND 2 AND 3') | |
); | |
}); | |
}); | |
}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Hi!
Just so you know, your file is good, but you could improve it by saying why you chose a solution over an other. For newbs like me, it helps understanding the internals of JS/ES
Anyway, for #56, last use case, you could do like this. It also works, and is less verbose (using destructuring+rest operator):
Hope this helps, and thanks again