Skip to content

Instantly share code, notes, and snippets.

@hanmd82
Last active January 2, 2018 14:48
Show Gist options
  • Save hanmd82/4c481955535676794c0c1195cf05a4aa to your computer and use it in GitHub Desktop.
Save hanmd82/4c481955535676794c0c1195cf05a4aa to your computer and use it in GitHub Desktop.
ES6 katas for Classes - http://es6katas.org/
// 22: class - creation
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 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() { return !this.everWroteATest }
}
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');
});
});
// 23: class - accessors
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 = amount; }
}
const account = new MyAccount();
account.balance = 23;
assert.equal(account.balance, 23);
});
});
});
// 24: class - static keyword
// Other than JavaScript instance methods (function that are associated with a particular JavaScript object),
// Javascript also has static methods - functions that are associated with the JavaScript class that created an object, as opposed to the object itself
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');
});
});
});
// 25: class - extends
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', () => {
// https://stackoverflow.com/q/41189190
class NullClass extends null {
constructor() {
return Object.create(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);
});
});
});
// 26: class - more-extends
describe('class can inherit from another', () => {
it('extend an `old style` "class", a function, still works', () => {
function A() {} // equivalent to class 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);
});
});
});
// 27: class - super inside a method
describe('inside a class use `super` to access parent methods', () => {
it('use of `super` without `extends` fails (already when transpiling)', () => {
class A {hasSuper() { return false; }}
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.undefined; }}
assert.equal(new B().getMethod(), void 0);
});
});
// 28: class - super in constructor
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(...args);
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() {
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);
// });
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment