|
|
@@ -143,4 +143,121 @@ describe( 'utils', () => {
|
|
|
yield 33;
|
|
|
}
|
|
|
} );
|
|
|
+
|
|
|
+ describe( 'mix', () => {
|
|
|
+ const MixinA = {
|
|
|
+ a() {
|
|
|
+ return 'a';
|
|
|
+ }
|
|
|
+ };
|
|
|
+ const MixinB = {
|
|
|
+ b() {
|
|
|
+ return 'b';
|
|
|
+ }
|
|
|
+ };
|
|
|
+
|
|
|
+ it( 'mixes 2nd+ param\'s properties into the first class', () => {
|
|
|
+ class Foo {}
|
|
|
+ utils.mix( Foo, MixinA, MixinB );
|
|
|
+
|
|
|
+ expect( Foo ).to.not.have.property( 'a' );
|
|
|
+ expect( Foo ).to.not.have.property( 'b' );
|
|
|
+
|
|
|
+ const foo = new Foo();
|
|
|
+
|
|
|
+ expect( foo.a() ).to.equal( 'a' );
|
|
|
+ expect( foo.b() ).to.equal( 'b' );
|
|
|
+ } );
|
|
|
+
|
|
|
+ it( 'does not break the instanceof operator', () => {
|
|
|
+ class Foo {}
|
|
|
+ utils.mix( Foo, MixinA );
|
|
|
+
|
|
|
+ let foo = new Foo();
|
|
|
+
|
|
|
+ expect( foo ).to.be.instanceof( Foo );
|
|
|
+ } );
|
|
|
+
|
|
|
+ it( 'defines properties with the same descriptors as native classes', () => {
|
|
|
+ class Foo {
|
|
|
+ foo() {}
|
|
|
+ }
|
|
|
+
|
|
|
+ utils.mix( Foo, MixinA );
|
|
|
+
|
|
|
+ const actualDescriptor = Object.getOwnPropertyDescriptor( Foo.prototype, 'a' );
|
|
|
+ const expectedDescriptor = Object.getOwnPropertyDescriptor( Foo.prototype, 'foo' );
|
|
|
+
|
|
|
+ expect( actualDescriptor ).to.have.property( 'writable', expectedDescriptor.writable );
|
|
|
+ expect( actualDescriptor ).to.have.property( 'enumerable', expectedDescriptor.enumerable );
|
|
|
+ expect( actualDescriptor ).to.have.property( 'configurable', expectedDescriptor.configurable );
|
|
|
+ } );
|
|
|
+
|
|
|
+ it( 'copies setters and getters (with descriptors as of native classes)', () => {
|
|
|
+ class Foo {
|
|
|
+ set foo( v ) {
|
|
|
+ this._foo = v;
|
|
|
+ }
|
|
|
+ get foo() {}
|
|
|
+ }
|
|
|
+
|
|
|
+ const Mixin = {
|
|
|
+ set a( v ) {
|
|
|
+ this._a = v;
|
|
|
+ },
|
|
|
+ get a() {
|
|
|
+ return this._a;
|
|
|
+ }
|
|
|
+ };
|
|
|
+
|
|
|
+ utils.mix( Foo, Mixin );
|
|
|
+
|
|
|
+ const actualDescriptor = Object.getOwnPropertyDescriptor( Foo.prototype, 'a' );
|
|
|
+ const expectedDescriptor = Object.getOwnPropertyDescriptor( Foo.prototype, 'foo' );
|
|
|
+
|
|
|
+ expect( actualDescriptor ).to.have.property( 'enumerable', expectedDescriptor.enumerable );
|
|
|
+ expect( actualDescriptor ).to.have.property( 'configurable', expectedDescriptor.configurable );
|
|
|
+
|
|
|
+ const foo = new Foo();
|
|
|
+
|
|
|
+ foo.a = 1;
|
|
|
+ expect( foo._a ).to.equal( 1 );
|
|
|
+
|
|
|
+ foo._a = 2;
|
|
|
+ expect( foo.a ).to.equal( 2 );
|
|
|
+ } );
|
|
|
+
|
|
|
+ it( 'copies symbols (with descriptors as of native classes)', () => {
|
|
|
+ const symbolA = Symbol( 'a' );
|
|
|
+ const symbolFoo = Symbol( 'foo' );
|
|
|
+
|
|
|
+ // https://github.com/jscs-dev/node-jscs/issues/2078
|
|
|
+ // jscs:disable disallowSpacesInFunction
|
|
|
+ class Foo {
|
|
|
+ [ symbolFoo ]() {
|
|
|
+ return 'foo';
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ const Mixin = {
|
|
|
+ [ symbolA ]() {
|
|
|
+ return 'a';
|
|
|
+ }
|
|
|
+ };
|
|
|
+ // jscs:enable disallowSpacesInFunction
|
|
|
+
|
|
|
+ utils.mix( Foo, Mixin );
|
|
|
+
|
|
|
+ const actualDescriptor = Object.getOwnPropertyDescriptor( Foo.prototype, symbolA );
|
|
|
+ const expectedDescriptor = Object.getOwnPropertyDescriptor( Foo.prototype, symbolFoo );
|
|
|
+
|
|
|
+ expect( actualDescriptor ).to.have.property( 'writable', expectedDescriptor.writable );
|
|
|
+ expect( actualDescriptor ).to.have.property( 'enumerable', expectedDescriptor.enumerable );
|
|
|
+ expect( actualDescriptor ).to.have.property( 'configurable', expectedDescriptor.configurable );
|
|
|
+
|
|
|
+ const foo = new Foo();
|
|
|
+
|
|
|
+ expect( foo[ symbolA ]() ).to.equal( 'a' );
|
|
|
+ } );
|
|
|
+ } );
|
|
|
} );
|