add esnext tests

This commit is contained in:
Sebastian McKenzie 2015-01-04 07:39:11 +11:00
parent 55123be7d7
commit cb54c11d84
63 changed files with 695 additions and 3 deletions

View File

@ -1,5 +1,6 @@
var fs = require("fs");
var _ = require("lodash");
var path = require("path");
var fs = require("fs");
var _ = require("lodash");
var humanise = function (val) {
return val.replace(/-/g, " ");
@ -37,7 +38,6 @@ exports.get = function (entryName) {
_.each(fs.readdirSync(suite.filename), function (taskName) {
var taskDir = suite.filename + "/" + taskName;
if (fs.statSync(taskDir).isFile()) return;
var actualLocAlias = suiteName + "/" + taskName + "/actual.js";
var expectLocAlias = suiteName + "/" + taskName + "/expected.js";
@ -47,6 +47,13 @@ exports.get = function (entryName) {
var expectLoc = taskDir + "/expected.js";
var execLoc = taskDir + "/exec.js";
if (fs.statSync(taskDir).isFile()) {
var ext = path.extname(taskDir);
if (ext === ".json") return;
execLoc = taskDir;
}
var taskOpts = _.merge({
filenameRelative: expectLocAlias,
sourceFileName: actualLocAlias,

View File

@ -0,0 +1,57 @@
function makeMultiplier() {
// `arguments` should refer to `makeMultiplier`'s arguments.
return (n) => [].slice.call(arguments).reduce((a, b) => a * b) * n;
}
function toArray() {
// Intentionally nest arrow functions to ensure `arguments` is put inside
// `toArray`'s scope.
return (() => (arguments, (() => [].slice.call(arguments)).call())).call();
}
function returnDotArguments(object) {
// Ensure `arguments` is not treated as a reference to the magic value.
return (() => object.arguments).call();
}
function returnArgumentsObject() {
// Ensure `arguments` is not treated as a reference to the magic value.
return (() => ({arguments: 1})).call();
}
function makeArgumentsReturner() {
return (() => function() {
return [].slice.call(arguments);
}).call();
}
// i.e. 2 * 3 * 4 == 24, not 16 (4 * 4)
assert.equal(
makeMultiplier(2, 3)(4),
24,
'ensure `arguments` is hoisted out to the first non-arrow scope'
);
assert.deepEqual(
toArray(1, 2, 3),
[1, 2, 3],
'ensure `arguments` is hoisted out to the first non-arrow scope'
);
assert.equal(
returnDotArguments({arguments: 1}),
1,
'member accesses with `arguments` property should not be replaced'
);
assert.deepEqual(
returnArgumentsObject(),
{arguments: 1},
'object property keys named `arguments` should not be replaced'
);
assert.deepEqual(
makeArgumentsReturner()(1, 2, 3),
[1, 2, 3],
'arguments should not be hoisted from inside non-arrow functions'
);

View File

@ -0,0 +1,5 @@
var dynamicThisGetter = () => function(){ return this; };
assert.equal(
normalize('('+dynamicThisGetter.toString()+')'),
normalize('(function(){ return function(){ return this; }; })')
);

View File

@ -0,0 +1,2 @@
var empty = () => {};
assert.equal(empty(), undefined);

View File

@ -0,0 +1,12 @@
var obj = {
method: function() {
return () => (this, () => this);
},
method2: function() {
return () => () => this;
}
};
assert.strictEqual(obj.method()()(), obj);
assert.strictEqual(obj.method2()()(), obj);

View File

@ -0,0 +1,2 @@
var square = x => x * x;
assert.equal(square(4), 16);

View File

@ -0,0 +1,2 @@
var keyMaker = val => ({ key: val });
assert.deepEqual(keyMaker(9), { key: 9 });

View File

@ -0,0 +1,7 @@
var obj = {
method: function() {
return () => this;
}
};
assert.strictEqual(obj.method()(), obj);

View File

@ -0,0 +1,2 @@
var odds = [0, 2, 4].map(v => v + 1);
assert.deepEqual(odds, [1, 3, 5]);

View File

@ -0,0 +1,2 @@
var identity = x => x;
assert.equal(identity(1), 1);

View File

@ -0,0 +1,29 @@
var Animal = class {
sayHi() {
return 'Hi, I am a '+this.type()+'.';
}
static getName() {
return 'Animal';
}
};
var Dog = class extends Animal {
type() { return 'dog'; }
sayHi() {
return super() + ' WOOF!';
}
static getName() {
return super() + '/Dog';
}
};
assert.equal(new Dog().sayHi(), 'Hi, I am a dog. WOOF!');
assert.equal(Dog.getName(), 'Animal/Dog');
var count = 0;
var Cat = class extends (function(){ count++; return Animal; })() {};
assert.equal(count, 1);

View File

@ -0,0 +1,21 @@
class Animal {
sayHi() {
return 'I am an animal.'
}
sayOther() {
return 'WAT?!';
}
}
class Horse extends Animal {
sayHi() {
return super.sayOther();
}
sayOther() {
return 'I see dead objects.';
}
}
assert.equal(new Horse().sayHi(), 'WAT?!');

View File

@ -0,0 +1,9 @@
var Person = (class Person {});
assert.equal(typeof Person, 'function');
assert.equal(
(function(){ return (class Person {}); })().name,
'Person'
);
assert.equal(typeof (class {}), 'function');

View File

@ -0,0 +1,15 @@
class Animal {
sayHi() {
return 'Hi, I am a '+this.type()+'.';
}
}
class Dog extends Animal {
type() { return 'dog'; }
sayHi() {
return super() + ' WOOF!';
}
}
assert.equal(new Dog().sayHi(), 'Hi, I am a dog. WOOF!');

View File

@ -0,0 +1,14 @@
class Multiplier {
constructor(n=1) {
this.n = n;
}
multiply(n=1) {
return n * this.n;
}
}
assert.equal(new Multiplier().n, 1);
assert.equal(new Multiplier(6).n, 6);
assert.equal(new Multiplier().multiply(), 1);
assert.equal(new Multiplier(2).multiply(3), 6);

View File

@ -0,0 +1,10 @@
class Person {
getName() {
return this.firstName + ' ' + this.lastName;
}
}
var me = new Person();
me.firstName = 'Brian';
me.lastName = 'Donovan';
assert.equal(me.getName(), 'Brian Donovan');

View File

@ -0,0 +1,5 @@
class Foo {
}
assert.equal(new Foo().constructor, Foo, 'Foo instances should have Foo as constructor');
assert.ok(new Foo() instanceof Foo, 'Foo instances should be `instanceof` Foo');

View File

@ -0,0 +1,20 @@
class Point {
constructor(x, y) {
this.x = x;
this.y = y;
}
toString() {
return '(' + this.x + ', ' + this.y + ')';
}
}
var point = new Point(1, 2);
var keys = [];
for (var key in point) {
keys.push(key);
}
assert.equal(point.toString(), '(1, 2)');
assert.deepEqual(keys.sort(), ['x', 'y']);

View File

@ -0,0 +1,15 @@
class Point {
constructor(x, y) {
this.x = x;
this.y = y;
}
}
class ZeroPoint extends Point {
constructor() {
super(0, 0);
}
}
assert.equal(new ZeroPoint().x, 0);
assert.equal(new ZeroPoint().y, 0);

View File

@ -0,0 +1,4 @@
class Obj extends null {}
assert.strictEqual(Obj.toString, Function.toString);
assert.strictEqual(new Obj().toString, undefined);

View File

@ -0,0 +1,15 @@
class Animal {
get sound() {
return 'I am a ' + this.type + '.';
}
}
class Cat extends Animal {
get type() { return 'cat'; }
get sound() {
return super.sound + ' MEOW!';
}
}
assert.equal(new Cat().sound, 'I am a cat. MEOW!');

View File

@ -0,0 +1,28 @@
class Person {
constructor(firstName, lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
get name() {
return this.firstName + ' ' + this.lastName;
}
set name(name) {
var parts = name.split(' ');
this.firstName = parts[0];
this.lastName = parts[1];
}
}
var mazer = new Person('Mazer', 'Rackham');
assert.equal(mazer.name, 'Mazer Rackham');
mazer.name = 'Ender Wiggin';
assert.equal(mazer.firstName, 'Ender');
assert.equal(mazer.lastName, 'Wiggin');
var forLoopProperties = [];
for (var key in mazer) {
forLoopProperties.push(key);
}
assert.ok(forLoopProperties.indexOf('name') >= 0, 'getters/setters are enumerable');

View File

@ -0,0 +1,9 @@
class Obj {
constructor() {
super();
}
}
assert.doesNotThrow(function() {
new Obj();
});

View File

@ -0,0 +1,7 @@
class Tripler {
triple(n) {
return n * 3;
}
}
assert.equal(new Tripler().triple(2), 6);

View File

@ -0,0 +1,12 @@
var value;
class Foo {
foo() {
value = 1;
}
}
var foo = new Foo();
foo.foo = function() { value = 2; };
foo.foo();
assert.equal(value, 2);

View File

@ -0,0 +1,28 @@
class Joiner {
constructor(string) {
this.string = string;
}
join(...items) {
return items.join(this.string);
}
static join(string, ...items) {
var joiner = new this(string);
// TODO: use spread params here
return joiner.join.apply(joiner, items);
}
}
class ArrayLike {
constructor(...items) {
items.forEach(function(item, i) {
this[i] = item;
}.bind(this));
this.length = items.length;
}
}
var joiner = new Joiner(' & ');
assert.equal(joiner.join(4, 5, 6), '4 & 5 & 6');
assert.equal(new ArrayLike('a', 'b')[1], 'b');

View File

@ -0,0 +1,12 @@
class Point {
constructor(x, y) {
this.x = x;
this.y = y;
}
static get ORIGIN() {
return new this(0, 0);
}
}
assert.deepEqual(Point.ORIGIN, new Point(0, 0));

View File

@ -0,0 +1,30 @@
class Tripler {
static triple(n=1) {
return n * 3;
}
static toString() {
return '3' + super() + '3';
}
}
class MegaTripler extends Tripler {
static triple(n=1) {
return super(n) * super(n);
}
}
var tripler = new Tripler();
assert.equal(Tripler.triple(), 3);
assert.equal(Tripler.triple(2), 6);
assert.equal(tripler.triple, undefined);
assert.equal(Tripler.toString(), '3' + Object.toString.call(Tripler) + '3');
var mega = new MegaTripler();
assert.equal(MegaTripler.triple(2), 36);
assert.equal(mega.triple, undefined);
assert.equal(MegaTripler.toString(), '3' + Object.toString.call(MegaTripler) + '3');

View File

@ -0,0 +1,7 @@
class Person {
static set DB(value) {
assert.equal(value, 'mysql');
}
}
Person.DB = 'mysql';

View File

@ -0,0 +1,23 @@
class StrictModeTest {
test() {
var implicitThisInsideClassBody = (function() {
return this;
})();
assert.strictEqual(
implicitThisInsideClassBody,
undefined,
'implicit `this` inside class body is undefined'
);
}
}
new StrictModeTest().test();
var implicitThisOutsideClass = (function() {
return this;
})();
assert.notStrictEqual(
implicitThisOutsideClass,
undefined,
'implicit `this` outside class body is not undefined'
);

View File

@ -0,0 +1,20 @@
var log = '';
class Base {
p() { log += '[Base]'; }
}
class OtherBase {
p() { log += '[OtherBase]'; }
}
class Derived extends Base {
p() {
log += '[Derived]';
super();
Derived.prototype.__proto__ = OtherBase.prototype;
super();
}
}
new Derived().p();
assert.equal(log, '[Derived][Base][OtherBase]');

View File

@ -0,0 +1,8 @@
var x = 'y';
var foo = {
get [x]() { return this._y; },
set [x](v) { this._y = v; }
};
assert.equal((foo.y = 10, foo.y), 10);

View File

@ -0,0 +1,3 @@
var x = 'y';
assert.equal({[x]: function() { return 10; }}.y(), 10);
assert.equal({[x + 'y']() { return 10; }}.yy(), 10);

View File

@ -0,0 +1,4 @@
var x = 'y';
var foo = {[x]: 10, z: {[x]: 10}};
assert.equal(foo.y + foo.z.y, 20);
assert.equal({[x]: {[x]: {[x]: 10}}}.y.y.y, 10);

View File

@ -0,0 +1,3 @@
var x = 'y';
assert.equal({[x]: 10}.y, 10);
assert.equal({[x + 'y']: 10}.yy, 10);

View File

@ -0,0 +1,3 @@
assert.equal((function(a){}).length, 1);
assert.equal((function(a=5){}).length, 0);
assert.equal((function(a, b, c=5){}).length, 2);

View File

@ -0,0 +1,8 @@
function makeMultiplier(x=1) {
return (y=1) => x * y;
}
assert.equal(makeMultiplier()(), 1);
assert.equal(makeMultiplier(2)(3), 6);
assert.deepEqual([1, 2, 3].map(makeMultiplier(2)), [2, 4, 6]);
assert.deepEqual([undefined, null, 0].map(makeMultiplier(2)), [2, 0, 0]);

View File

@ -0,0 +1,5 @@
function foo(x=5, y=6) {
return [x, y];
}
assert.deepEqual(foo(undefined, null), [5, null]);

View File

@ -0,0 +1,11 @@
function call(fn, context=this) {
return fn.call(context);
}
var context = {a: 99};
// use the default parameter
assert.strictEqual(call.call(context, function(){ return this.a; }), 99);
// explicitly provide the default parameter value
assert.strictEqual(call(function(){ return this.a; }, context), 99);

View File

@ -0,0 +1,4 @@
function foo(x=5) {
return x;
}
assert.equal(foo(), 5);

View File

@ -0,0 +1,7 @@
var a = {
echo(c) {
return c;
}
};
assert.strictEqual(a.echo(1), 1);

View File

@ -0,0 +1,9 @@
var a = {
b() {
return this;
}
};
var context = {};
assert.strictEqual(a.b(), a);
assert.strictEqual(a.b.call(context), context);

View File

@ -0,0 +1,7 @@
var a = {
b() {
return 'c';
}
};
assert.equal(a.b.name, 'b');

View File

@ -0,0 +1,9 @@
var b = 1;
var a = {
b() {
return b;
}
};
assert.equal(a.b(), 1);

View File

@ -0,0 +1,10 @@
var a = {
b() {
return b;
}
};
assert.ok(
/return b/.test(a.b.toString()),
'toString contains body'
);

View File

@ -0,0 +1,7 @@
var a = {
b() {
return 'c';
}
};
assert.equal(a.b(), 'c');

View File

@ -0,0 +1,8 @@
/* jshint esnext: true */
/* global expect */
var join = (joinStr, ...items) => {
return items.join(joinStr);
};
expect(join(' ', 'a', 'b', 'c')).to.equal('a b c');

View File

@ -0,0 +1,8 @@
/* jshint esnext: true */
/* global expect */
function join(joinStr, ...items) {
return items.join(joinStr);
}
expect(join(' ', 'a', 'b', 'c')).to.equal('a b c');

View File

@ -0,0 +1,8 @@
/* jshint esnext: true */
/* global expect */
var join = function(joinStr, ...items) {
return items.join(joinStr);
};
expect(join(' ', 'a', 'b', 'c')).to.equal('a b c');

View File

@ -0,0 +1,6 @@
function arrayOf() {
return [...arguments];
}
assert.equal(Object.prototype.toString.call(arrayOf()), '[object Array]');
assert.deepEqual(arrayOf(1, 2, 3), [1, 2, 3]);

View File

@ -0,0 +1,3 @@
var names = ['Brian', 'Madeline'];
assert.deepEqual(['Thomas', ...names], ['Thomas', 'Brian', 'Madeline']);
assert.deepEqual([1, 2, ...[3, 4, 5]], [1, 2, 3, 4, 5]);

View File

@ -0,0 +1,5 @@
function sum(...numbers) {
return numbers.reduce(function(sum, n) { return n + sum; }, 0);
}
assert.equal(sum(4, 5, ...[10, 20, 30]), 69);

View File

@ -0,0 +1,10 @@
var object = {
list: [],
append: function(...items) {
this.list.push(...items);
}
};
object.append(1, 2, ...[3, 4]);
assert.deepEqual(object.list, [1, 2, 3, 4]);

View File

@ -0,0 +1,19 @@
function Symbol() {}
Symbol.iterator = '@@iterator';
var obj = {
'@@iterator': function() {
var ttl = 3;
return {
next: function() {
if (ttl === 0) {
return { done: true, value: null };
} else {
return { done: false, value: ttl-- };
}
}
};
}
};
assert.deepEqual([3, 2, 1], [...obj]);

View File

@ -0,0 +1,11 @@
var callCount = 0;
function getArray() {
callCount++;
return Array;
}
assert.deepEqual([1, 2, 3], new Array(...[1, 2, 3]));
// Ensure the expression of the function being initialized is not copied.
assert.deepEqual([1, 2, 3], new (getArray())(...[1, 2, 3]));
assert.equal(callCount, 1);

View File

@ -0,0 +1,35 @@
var MATH = {
sum: function(...numbers) {
return numbers.reduce(this.add, 0);
},
add: function(a, b) {
return a + b;
}
};
assert.equal(MATH.sum(1, ...[2, 3]), 6);
// Ensure that the below does not expand to this:
//
// obj.getSelf().call.apply(obj.getSelf(), []);
//
var ops = [];
var obj = {
getSelf: function() {
ops.push('getSelf');
return this;
},
doCall: function() {
ops.push('doCall', this);
}
};
obj.getSelf().doCall(...[]);
assert.deepEqual(ops, ['getSelf', 'doCall', obj]);
ops = [];
obj['getSelf']().doCall(...[]);
assert.deepEqual(ops, ['getSelf', 'doCall', obj]);

View File

@ -0,0 +1,6 @@
function sum(...numbers) {
return numbers.reduce(function(sum, n) { return n + sum; }, 0);
}
var numbers = [1, 2, 3];
assert.equal(sum(...numbers), 6);

View File

@ -0,0 +1,4 @@
var s = `a
b
c`;
assert.equal(s, 'a\n b\n c');

View File

@ -0,0 +1,4 @@
assert.strictEqual(
`a${1}b${`${1+1}c`}3`,
'a1b2c3'
);

View File

@ -0,0 +1,2 @@
var s = `str`;
assert.equal(s, 'str');

View File

@ -0,0 +1,6 @@
function r(strings) {
assert.equal(strings.raw[0], '\\n');
return strings.raw.join('');
}
assert.equal(r `\n`, '\\n');

View File

@ -0,0 +1,2 @@
var s = `1 + 1 = ${1 + 1}`;
assert.equal(s, '1 + 1 = 2');

View File

@ -0,0 +1,26 @@
function tag(strings) {
var values = [].slice.call(arguments, 1);
assert.equal(strings[0], 'a');
assert.equal(strings[1], 'b');
assert.equal(values[0], 42);
return 'whatever';
}
assert.equal(tag `a${ 42 }b`, 'whatever');
function tagInterpolateFirst(strings) {
var values = [].slice.call(arguments, 1);
assert.equal(strings[0], '');
assert.equal(strings[1], 'b');
assert.equal(values[0], 42);
return 'whatever';
}
assert.equal(tagInterpolateFirst `${ 42 }b`, 'whatever');
function tagInterpolateLast(strings) {
var values = [].slice.call(arguments, 1);
assert.equal(strings[0], 'a');
assert.equal(strings[1], '');
assert.equal(values[0], 42);
return 'whatever';
}
assert.equal(tagInterpolateLast `a${ 42 }`, 'whatever');