Skip to content

Commit

Permalink
Lots of GIVEN-WHEN-THENing, but also added String.raw ...
Browse files Browse the repository at this point in the history
  • Loading branch information
wolframkriesing committed Oct 8, 2023
1 parent 1e19639 commit c4558a5
Show file tree
Hide file tree
Showing 11 changed files with 274 additions and 92 deletions.
4 changes: 2 additions & 2 deletions katas/es1/language/unary-operators/all.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ describe('All unary operators', () => {
var trueString = !'true';
assert.strictEqual(!trueString, false);
});
it('AND it is `delete` before an object`s property THEN the property is removed', () => {
it('AND it is `delete` before an object\'s property THEN the property is removed', () => {
var obj = {x: 1};
delete obj.axe;
assert.strictEqual(obj.x, undefined);
Expand All @@ -35,7 +35,7 @@ describe('All unary operators', () => {
var toUndefined = delete {any: 'thing'};
assert.strictEqual(toUndefined, undefined);
});
it('AND it is `typeof` THEN it returns the operand`s type', () => {
it('AND it is `typeof` THEN it returns the operand\'s type', () => {
var whatsTheType = typeof '42';
assert.strictEqual(whatsTheType, 'number');
});
Expand Down
2 changes: 1 addition & 1 deletion katas/es1/language/unary-operators/plus-in-depth.js
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ describe('Unary "+" operator', () => {
var Class = class{toString = () => '123'};
assert.strictEqual(+new Class, 23);
});
it('AND its a class with `valueOf()` and `toString()` THEN `valueOf`s value is used', () => {
it('AND its a class with `valueOf()` and `toString()` THEN `valueOf`\'s value is used', () => {
var toString = () => '23';
var valueOf = toString;
assert.strictEqual(+new class{toString = toString; valueOf = valueOf}, 42);
Expand Down
67 changes: 65 additions & 2 deletions katas/es6/language/__all__.json
Original file line number Diff line number Diff line change
Expand Up @@ -88,9 +88,9 @@
},
{
"name": "`raw` property",
"description": "The `raw` property accesses the string as it was entered.",
"description": "The `raw` property can access the string without processing escape sequences.",
"path": "template-strings/raw",
"level": "INTERMEDIATE",
"level": "EXPERT",
"requiresKnowledgeFrom": [
{
"bundle": "es6/language",
Expand All @@ -99,6 +99,10 @@
{
"bundle": "es6/language",
"id": 3
},
{
"bundle": "es6/language",
"id": 82
}
],
"links": [
Expand All @@ -116,6 +120,13 @@
"tags": [
"spec"
]
},
{
"url": "https://tc39.es/ecma262/#sec-gettemplateobject",
"comment": "The JS engine internal abstract operation `GetTemplateObject` describes how the template object, that is passed to the tag-function is created, see esp. the adding of the `raw` property onto the array here (item: 14. Perform ! DefinePropertyOrThrow(template, \"raw\"...).",
"tags": [
"spec"
]
}
],
"groupName": "Template strings",
Expand Down Expand Up @@ -2294,6 +2305,58 @@
"groupNameSlug": "number-api",
"publishDateRfc822": "Sun, 06 Oct 2019 17:29:00 GMT",
"id": 81
},
{
"name": "`String.raw`",
"description": "`String.raw` is a tag function for a template literal, which returns the raw string, e.g. \\n (not \n) for a line break.",
"path": "string-api/raw",
"level": "ADVANCED",
"requiresKnowledgeFrom": [
{
"bundle": "es6/language",
"id": 8
},
{
"bundle": "es6/language",
"id": 5
},
{
"bundle": "es6/language",
"id": 18
},
{
"bundle": "es6/language",
"id": 20
}
],
"links": [
{
"url": "https://262.ecma-international.org/6.0/#sec-string.raw",
"comment": "The original official specification when introduced, it does not explain what this function does, but very much in detail how it works which results in explaining the \"what\" too.",
"tags": [
"spec"
]
},
{
"url": "https://tc39.es/ecma262/#sec-string.raw",
"comment": "The more readable and usable specification, in the version of the continuously maintained specification document.",
"tags": [
"spec"
]
},
{
"url": "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/raw",
"comment": "The Mozilla Developer Network docs, an easy to understand explanation.",
"tags": [
"mdn",
"docs"
]
}
],
"groupName": "String API",
"groupNameSlug": "string-api",
"publishDateRfc822": "Sun, 08 Oct 2023 19:15:00 GMT",
"id": 82
}
]
}
66 changes: 64 additions & 2 deletions katas/es6/language/__grouped__.json
Original file line number Diff line number Diff line change
Expand Up @@ -87,9 +87,9 @@
},
{
"name": "`raw` property",
"description": "The `raw` property accesses the string as it was entered.",
"description": "The `raw` property can access the string without processing escape sequences.",
"path": "template-strings/raw",
"level": "INTERMEDIATE",
"level": "EXPERT",
"requiresKnowledgeFrom": [
{
"bundle": "es6/language",
Expand All @@ -98,6 +98,10 @@
{
"bundle": "es6/language",
"id": 3
},
{
"bundle": "es6/language",
"id": 82
}
],
"publishDateUTC": "2015-03-18T07:55:00.000Z",
Expand All @@ -116,6 +120,13 @@
"tags": [
"spec"
]
},
{
"url": "https://tc39.es/ecma262/#sec-gettemplateobject",
"comment": "The JS engine internal abstract operation `GetTemplateObject` describes how the template object, that is passed to the tag-function is created, see esp. the adding of the `raw` property onto the array here (item: 14. Perform ! DefinePropertyOrThrow(template, \"raw\"...).",
"tags": [
"spec"
]
}
],
"groupName": "Template strings",
Expand Down Expand Up @@ -2103,6 +2114,57 @@
],
"groupName": "String API",
"id": "74"
},
{
"name": "`String.raw`",
"description": "`String.raw` is a tag function for a template literal, which returns the raw string, e.g. \\n (not \n) for a line break.",
"path": "string-api/raw",
"level": "ADVANCED",
"requiresKnowledgeFrom": [
{
"bundle": "es6/language",
"id": 8
},
{
"bundle": "es6/language",
"id": 5
},
{
"bundle": "es6/language",
"id": 18
},
{
"bundle": "es6/language",
"id": 20
}
],
"publishDateUTC": "2023-10-08T19:15:00.000Z",
"links": [
{
"url": "https://262.ecma-international.org/6.0/#sec-string.raw",
"comment": "The original official specification when introduced, it does not explain what this function does, but very much in detail how it works which results in explaining the \"what\" too.",
"tags": [
"spec"
]
},
{
"url": "https://tc39.es/ecma262/#sec-string.raw",
"comment": "The more readable and usable specification, in the version of the continuously maintained specification document.",
"tags": [
"spec"
]
},
{
"url": "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/raw",
"comment": "The Mozilla Developer Network docs, an easy to understand explanation.",
"tags": [
"mdn",
"docs"
]
}
],
"groupName": "String API",
"id": "82"
}
],
"slug": "string-api",
Expand Down
2 changes: 1 addition & 1 deletion katas/es6/language/map/set.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ describe('`Map.prototype.set` adds a new element with key and value to a Map', f
map.set('key', 'value3');
assert.equal(map.get('key'), 'value1');
});
it('`set()` returns the map object, it`s chainable', function() {
it('`set()` returns the map object, it\'s chainable', function() {
let map = new Map();
map.set(1, 'one')
.set(2, 'two')
Expand Down
70 changes: 37 additions & 33 deletions katas/es6/language/string-api/includes.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,80 +3,84 @@
// Follow the hints of the failure messages!


describe('`string.includes()` determines if a string can be found inside another one', function() {
describe('finding a single character', function() {
it('can be done (a character is also a string, in JS)', function() {
describe('`string.includes()` finds one string inside another', function() {
describe('GIVEN searching a single character', function() {
it('WHEN "x" is found THEN then `s.includes("x")` returns true', function() {
const searchString = 'a';
assert.equal('xyz'.includes(searchString), true);
});
it('reports false if character was not found', function() {
it('WHEN the searched character is not contained THEN it returns false', function() {
const actual = '???';
assert.equal(actual, 'xyz'.includes('abc'));
});
});
describe('find a string', function() {
it('that matches exactly', function() {
describe('GIVEN searching for a string', function() {
it('WHEN the searched string matches exactly THEN `true` is returned', function() {
const findSome = findMe => 'xyz'.includes;
assert.equal(findSome('xyz'), true);
});
it('WHEN searching for "A" THEN "a" is not found, the search is case-sensitive', function() {
const findInAbc = (what) => 'abc'.inkludez(what);
assert.equal(findInAbc('A'), false);
});
});
describe('search for an empty string, is always true', function() {
it('in an empty string', function() {
describe('GIVEN the searched string is an empty string `""` it is always found', function() {
it('WHEN the searching in an empty string THEN this returns `true`', function() {
const emptyString = ' ';
assert.equal(''.includes(emptyString), true);
});
it('in `abc`', function() {
it('WHEN the searched string is NOT empty THEN `s.includes("")` returns true', function() {
const actual = _.includes('');
assert.equal(actual, true);
});
});
describe('special/corner cases', function() {
it('search for `undefined` in a string fails', function() {
const findInAbc = (what) => 'abc'.includes;
assert.equal(findInAbc(undefined), false);
});
it('searches are case-sensitive', function() {
const findInAbc = (what) => 'abc'.inkludez(what);
assert.equal(findInAbc('A'), false);
});
it('must NOT be a regular expression', function() {
const regExp = '';
assert.throws(() => {''.includes(regExp)});
});
describe('coerces the searched "thing" into a string', function() {
it('e.g. from a number', function() {
describe('GIVEN we use not only strings', function() {
describe('JavaScript tries to coerce (convert) the parameter to a string', function() {
it('WHEN searching for the number `4` THEN it is found in a string that contains it', function() {
const actual = '123'.includes(4);
assert.equal(actual, true);
});
it('e.g. from an array', function() {
it('WHEN searching for an array THEN the array is coerced to a string first', function() {
const actual = '123'.includes([1,2,3]);
assert.equal(actual, true);
});
it('e.g. from an object, with a `toString()` method', function() {
it('WHEN searching with an object that has a `toString()` method THEN the result of that function call is used as search string', function() {
const objWithToString = {toString: 1};
assert.equal('123'.includes(objWithToString), true);
});
});
describe('some searches you should prevent', () => {
it('WHEN searching for `undefined` in a string THEN this returns `false`', function() {
const findInAbc = (what) => 'abc'.includes;
assert.equal(findInAbc(undefined), false);
});
it('WHEN the search parameter is a regular expression THEN `includes()` throws an error', function() {
const regExp = '';
assert.throws(() => {
''.includes(regExp);
});
});
});
});
describe('takes a position from where to start searching', function() {
it('does not find `a` after position 1 in `abc`', function() {
describe('GIVEN a 1st parameter, the position where to start searching from', function() {
it('WHEN given `1` THEN it does not find `a` after position 1 in `abc`', function() {
const position = 0;
assert.equal('abc'.includes('a', position), false);
});
it('even the position gets coerced', function() {
it('WHEN the position is given as a string THEN it gets coerced to a number', function() {
const findAtPosition = position => 'xyz'.includes('x', pos);
assert.equal(findAtPosition('2'), false);
});
describe('invalid positions get converted to 0', function() {
it('e.g. `undefined`', function() {
describe('GIVEN an invalid positions parameter, it gets converted to 0', function() {
it('WHEN passing `undefined` THEN the search starts at position 0', function() {
const findAtPosition = (pos=2) => 'xyz'.includes('x', pos);
assert.equal(findAtPosition(undefined), true);
});
it('negative numbers', function() {
it('WHEN given a negative numbers THEN the search starts at position 0', function() {
const findAtPosition = (pos) => 'xyz'.includes('x', -pos);
assert.equal(findAtPosition(-2), true);
});
it('NaN', function() {
it('WHEN given `NaN` THEN the search starts at position 0', function() {
const findAtPosition = (pos) => 'xyz'.includes('x', 1);
assert.equal(findAtPosition(NaN), true);
});
Expand Down
41 changes: 41 additions & 0 deletions katas/es6/language/string-api/raw.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import assert from "assert";

describe('`String.raw` provides the raw string of a template literal', function() {
describe('GIVEN using `String.raw` as a tag-function', () => {
it('WHEN passing line-break (\\n) THEN the `String.raw` of it escapes the backslash and makes it "visible"', function() {
var expected = '\n';
assert.equal(String.raw`\n`, expected);
});
it('WHEN passing an escaped backslash to `String.raw` THEN this equals a string with two backslashes, where each is escaped', function() {
const TWO_BACKSLASHES = '\\';
assert.equal(String.raw`\\`, TWO_BACKSLASHES);
});
it('WHEN passing a unicode character THEN the leading backslash is made "visible"', function() {
var rawSmilie = '\u{1F600}';
const actual = String.raw`\u{1F600}`;
assert.equal(actual, rawSmilie);
});
});
describe('GIVEN using `String.raw` as a function to call', () => {
it('WHEN `String.raw()` is called without a parameter THEN it throws', () => {
const callingStringRaw = () => String.raw;
assert.throws(callingStringRaw, TypeError);
});
it('WHEN `String.raw()` is called with a string as parameter THEN it still throws', () => {
const callRawWithAString = () => String.raw({raw: 'a string'});
assert.throws(callRawWithAString, TypeError);
});
it('WHEN passing the first parameter `{raw: []}` THEN this equals to an empty string', () => {
const firstParam = {raw: undefined};
assert.equal(String.raw(firstParam), '');
});
it('WHEN passing the first property `raw` an array of strings THEN they are just concatenated', () => {
const expected = 'a,b,c';
assert.equal(String.raw({raw: ['a', 'b', 'c']}), expected);
});
it('WHEN passing more parameters, the substitutions THEN these are used as the filler between each raw string, in their according place', () => {
const rawStrings = ['-', '-'];
assert.equal(String.raw({raw: rawStrings}, 1, 2), '.1-2.');
});
});
});
Loading

0 comments on commit c4558a5

Please sign in to comment.