소스 검색

Extract methods from utils/utils object to separated files

Oskar Wrobel 9 년 전
부모
커밋
a6f8834723

+ 4 - 3
packages/ckeditor5-utils/src/collection.js

@@ -7,7 +7,8 @@
 
 
 import EmitterMixin from './emittermixin.js';
 import EmitterMixin from './emittermixin.js';
 import CKEditorError from './ckeditorerror.js';
 import CKEditorError from './ckeditorerror.js';
-import utils from './utils.js';
+import uid from './uid.js';
+import mix from './mix.js';
 
 
 /**
 /**
  * Collections are ordered sets of objects. Items in the collection can be retrieved by their indexes
  * Collections are ordered sets of objects. Items in the collection can be retrieved by their indexes
@@ -268,14 +269,14 @@ export default class Collection {
 		let id;
 		let id;
 
 
 		do {
 		do {
-			id = String( utils.uid() );
+			id = String( uid() );
 		} while ( this._itemMap.has( id ) );
 		} while ( this._itemMap.has( id ) );
 
 
 		return id;
 		return id;
 	}
 	}
 }
 }
 
 
-utils.mix( Collection, EmitterMixin );
+mix( Collection, EmitterMixin );
 
 
 /**
 /**
  * Fired when an item is added to the collection.
  * Fired when an item is added to the collection.

+ 46 - 0
packages/ckeditor5-utils/src/comparearrays.js

@@ -0,0 +1,46 @@
+/**
+ * @license Copyright (c) 2003-2016, CKSource - Frederico Knabben. All rights reserved.
+ * For licensing, see LICENSE.md.
+ */
+
+'use strict';
+
+/**
+ * Compares how given arrays relate to each other. One array can be: same as another array, prefix of another array
+ * or completely different. If arrays are different, first index at which they differ is returned. Otherwise,
+ * a flag specifying the relation is returned. Flags are negative numbers, so whenever a number >= 0 is returned
+ * it means that arrays differ.
+ *
+ *		compareArrays( [ 0, 2 ], [ 0, 2 ] );		// 'SAME'
+ *		compareArrays( [ 0, 2 ], [ 0, 2, 1 ] );		// 'PREFIX'
+ *		compareArrays( [ 0, 2 ], [ 0 ] );			// 'EXTENSION'
+ *		compareArrays( [ 0, 2 ], [ 1, 2 ] );		// 0
+ *		compareArrays( [ 0, 2 ], [ 0, 1 ] );		// 1
+ *
+ * @memberOf utils
+ * @param {Array} a Array that is compared.
+ * @param {Array} b Array to compare with.
+ * @returns {utils.ArrayRelation} How array `a` is related to `b`.
+ */
+export default function( a, b ) {
+	const minLen = Math.min( a.length, b.length );
+
+	for ( let i = 0; i < minLen; i++ ) {
+		if ( a[ i ] != b[ i ] ) {
+			// The arrays are different.
+			return i;
+		}
+	}
+
+	// Both arrays were same at all points.
+	if ( a.length == b.length ) {
+		// If their length is also same, they are the same.
+		return 'SAME';
+	} else if ( a.length < b.length ) {
+		// Compared array is shorter so it is a prefix of the other array.
+		return 'PREFIX';
+	} else {
+		// Compared array is longer so it is an extension of the other array.
+		return 'EXTENSION';
+	}
+}

+ 2 - 2
packages/ckeditor5-utils/src/config.js

@@ -8,7 +8,7 @@
 import ObservableMixin from './observablemixin.js';
 import ObservableMixin from './observablemixin.js';
 import isObject from './lib/lodash/isObject.js';
 import isObject from './lib/lodash/isObject.js';
 import isPlainObject from './lib/lodash/isPlainObject.js';
 import isPlainObject from './lib/lodash/isPlainObject.js';
-import utils from './utils.js';
+import mix from './mix.js';
 
 
 /**
 /**
  * Handles a configuration dictionary.
  * Handles a configuration dictionary.
@@ -188,4 +188,4 @@ export default class Config {
 	}
 	}
 }
 }
 
 
-utils.mix( Config, ObservableMixin );
+mix( Config, ObservableMixin );

+ 25 - 0
packages/ckeditor5-utils/src/count.js

@@ -0,0 +1,25 @@
+/**
+ * @license Copyright (c) 2003-2016, CKSource - Frederico Knabben. All rights reserved.
+ * For licensing, see LICENSE.md.
+ */
+
+'use strict';
+
+/**
+ * Returns the number of items return by the iterator.
+ *
+ *		count( [ 1, 2, 3, 4, 5 ] ); // 5;
+ *
+ * @memberOf utils
+ * @param {Iterable.<*>} iterator Any iterator.
+ * @returns {Number} Number of items returned by that iterator.
+ */
+export default function( iterator ) {
+	let count = 0;
+
+	for ( let _ of iterator ) { // jshint ignore:line
+		count++;
+	}
+
+	return count;
+}

+ 3 - 3
packages/ckeditor5-utils/src/dom/createelement.js

@@ -6,7 +6,7 @@
 'use strict';
 'use strict';
 
 
 import isString from '../lib/lodash/isString.js';
 import isString from '../lib/lodash/isString.js';
-import utils from '../utils.js';
+import isIterable from '../isiterable.js';
 
 
 /**
 /**
  * Creates element with attributes and children.
  * Creates element with attributes and children.
@@ -31,7 +31,7 @@ export default function createElement( doc, name, attributes = {}, children = []
 		element.setAttribute( key, attributes[ key ] );
 		element.setAttribute( key, attributes[ key ] );
 	}
 	}
 
 
-	if ( isString( children ) || !utils.isIterable( children ) ) {
+	if ( isString( children ) || !isIterable( children ) ) {
 		children = [ children ];
 		children = [ children ];
 	}
 	}
 
 
@@ -44,4 +44,4 @@ export default function createElement( doc, name, attributes = {}, children = []
 	}
 	}
 
 
 	return element;
 	return element;
-}
+}

+ 2 - 2
packages/ckeditor5-utils/src/emittermixin.js

@@ -6,7 +6,7 @@
 'use strict';
 'use strict';
 
 
 import EventInfo from './eventinfo.js';
 import EventInfo from './eventinfo.js';
-import utils from './utils.js';
+import uid from './uid.js';
 
 
 // Saves how many callbacks has been already added. Does not decrement when callback is removed.
 // Saves how many callbacks has been already added. Does not decrement when callback is removed.
 // Used internally as a unique id for a callback.
 // Used internally as a unique id for a callback.
@@ -159,7 +159,7 @@ const EmitterMixin = {
 		}
 		}
 
 
 		if ( !( emitterId = emitter._emitterId ) ) {
 		if ( !( emitterId = emitter._emitterId ) ) {
-			emitterId = emitter._emitterId = utils.uid();
+			emitterId = emitter._emitterId = uid();
 		}
 		}
 
 
 		if ( !( emitterInfo = emitters[ emitterId ] ) ) {
 		if ( !( emitterInfo = emitters[ emitterId ] ) ) {

+ 3 - 3
packages/ckeditor5-utils/src/eventinfo.js

@@ -5,7 +5,7 @@
 
 
 'use strict';
 'use strict';
 
 
-import utils from './utils.js';
+import spy from './spy.js';
 
 
 /**
 /**
  * The event object passed to event callbacks. It is used to provide information about the event as well as a tool to
  * The event object passed to event callbacks. It is used to provide information about the event as well as a tool to
@@ -36,13 +36,13 @@ export default class EventInfo {
 		 *
 		 *
 		 * @method utils.EventInfo#stop
 		 * @method utils.EventInfo#stop
 		 */
 		 */
-		this.stop = utils.spy();
+		this.stop = spy();
 
 
 		/**
 		/**
 		 * Removes the current callback from future interactions of this event.
 		 * Removes the current callback from future interactions of this event.
 		 *
 		 *
 		 * @method utils.EventInfo#off
 		 * @method utils.EventInfo#off
 		 */
 		 */
-		this.off = utils.spy();
+		this.off = spy();
 	}
 	}
 }
 }

+ 17 - 0
packages/ckeditor5-utils/src/isIterable.js

@@ -0,0 +1,17 @@
+/**
+ * @license Copyright (c) 2003-2016, CKSource - Frederico Knabben. All rights reserved.
+ * For licensing, see LICENSE.md.
+ */
+
+'use strict';
+
+/**
+ * Checks if value implements iterator interface.
+ *
+ * @memberOf utils
+ * @param {*} value The value to check.
+ * @returns {Boolean} True if value implements iterator interface.
+ */
+export default function( value ) {
+	return !!( value && value[ Symbol.iterator ] );
+}

+ 29 - 0
packages/ckeditor5-utils/src/mapsequal.js

@@ -0,0 +1,29 @@
+/**
+ * @license Copyright (c) 2003-2016, CKSource - Frederico Knabben. All rights reserved.
+ * For licensing, see LICENSE.md.
+ */
+
+'use strict';
+
+/**
+ * Checks whether given {Map}s are equal, that is has same size and same key-value pairs.
+ *
+ * @memberOf utils
+ * @returns {Boolean} `true` if given maps are equal, `false` otherwise.
+ */
+export default function( mapA, mapB ) {
+	if ( mapA.size != mapB.size ) {
+		return false;
+	}
+
+	for ( let attr of mapA.entries() ) {
+		let valA = JSON.stringify( attr[ 1 ] );
+		let valB = JSON.stringify( mapB.get( attr[ 0 ] ) );
+
+		if ( valA !== valB ) {
+			return false;
+		}
+	}
+
+	return true;
+}

+ 46 - 0
packages/ckeditor5-utils/src/mix.js

@@ -0,0 +1,46 @@
+/**
+ * @license Copyright (c) 2003-2016, CKSource - Frederico Knabben. All rights reserved.
+ * For licensing, see LICENSE.md.
+ */
+
+'use strict';
+
+/**
+ * Copies enumerable properties and symbols from the objects given as 2nd+ parameters to the
+ * prototype of first object (a constructor).
+ *
+ *		class Editor {
+ *			...
+ *		}
+ *
+ *		const SomeMixin = {
+ *			a() {
+ *				return 'a';
+ *			}
+ *		};
+ *
+ *		mix( Editor, SomeMixin, ... );
+ *
+ *		new Editor().a(); // -> 'a'
+ *
+ * Note: Properties which already exist in the base class will not be overriden.
+ *
+ * @memberOf utils
+ * @param {Function} [baseClass] Class which prototype will be extended.
+ * @param {Object} [...mixins] Objects from which to get properties.
+ */
+export default function( baseClass, ...mixins ) {
+	mixins.forEach( ( mixin ) => {
+		Object.getOwnPropertyNames( mixin ).concat( Object.getOwnPropertySymbols( mixin ) )
+			.forEach( ( key ) => {
+				if ( key in baseClass.prototype ) {
+					return;
+				}
+
+				const sourceDescriptor = Object.getOwnPropertyDescriptor( mixin, key );
+				sourceDescriptor.enumerable = false;
+
+				Object.defineProperty( baseClass.prototype, key, sourceDescriptor );
+			} );
+	} );
+}

+ 25 - 0
packages/ckeditor5-utils/src/nth.js

@@ -0,0 +1,25 @@
+/**
+ * @license Copyright (c) 2003-2016, CKSource - Frederico Knabben. All rights reserved.
+ * For licensing, see LICENSE.md.
+ */
+
+'use strict';
+
+/**
+ * Returns `nth` (starts from `0` of course) item of an `iterable`.
+ *
+ * @memberOf utils
+ * @param {Number} index
+ * @param {Iterable.<*>} iterable
+ * @returns {*}
+ */
+export default function( index, iterable ) {
+	for ( let item of iterable ) {
+		if ( index === 0 ) {
+			return item;
+		}
+		index -= 1;
+	}
+
+	return null;
+}

+ 26 - 0
packages/ckeditor5-utils/src/objecttomap.js

@@ -0,0 +1,26 @@
+/**
+ * @license Copyright (c) 2003-2016, CKSource - Frederico Knabben. All rights reserved.
+ * For licensing, see LICENSE.md.
+ */
+
+'use strict';
+
+/**
+ * Transforms object to map.
+ *
+ *		const map = objectToMap( { 'foo': 1, 'bar': 2 } );
+ *		map.get( 'foo' ); // 1
+ *
+ * @memberOf utils
+ * @param {Object} obj Object to transform.
+ * @returns {Map} Map created from object.
+ */
+export default function( obj ) {
+	const map = new Map();
+
+	for ( let key in obj ) {
+		map.set( key, obj[ key ] );
+	}
+
+	return map;
+}

+ 22 - 0
packages/ckeditor5-utils/src/spy.js

@@ -0,0 +1,22 @@
+/**
+ * @license Copyright (c) 2003-2016, CKSource - Frederico Knabben. All rights reserved.
+ * For licensing, see LICENSE.md.
+ */
+
+'use strict';
+
+/**
+ * Creates a spy function (ala Sinon.js) that can be used to inspect call to it.
+ *
+ * The following are the present features:
+ *
+ * * spy.called: property set to `true` if the function has been called at least once.
+ *
+ * @memberOf utils
+ * @returns {Function} The spy function.
+ */
+export default function() {
+	return function spy() {
+		spy.called = true;
+	};
+}

+ 28 - 0
packages/ckeditor5-utils/src/tomap.js

@@ -0,0 +1,28 @@
+/**
+ * @license Copyright (c) 2003-2016, CKSource - Frederico Knabben. All rights reserved.
+ * For licensing, see LICENSE.md.
+ */
+
+'use strict';
+
+import isPlainObject from './lib/lodash/isPlainObject.js';
+import objectToMap from './objecttomap.js';
+
+/**
+ * Transforms object or iterable to map. Iterable needs to be in the format acceptable by the `Map` constructor.
+ *
+ *		map = toMap( { 'foo': 1, 'bar': 2 } );
+ *		map = toMap( [ [ 'foo', 1 ], [ 'bar', 2 ] ] );
+ *		map = toMap( anotherMap );
+ *
+ * @memberOf utils
+ * @param {Object|Iterable} data Object or iterable to transform.
+ * @returns {Map} Map created from data.
+ */
+export default function( data ) {
+	if ( isPlainObject( data ) ) {
+		return objectToMap( data );
+	} else {
+		return new Map( data );
+	}
+}

+ 22 - 0
packages/ckeditor5-utils/src/uid.js

@@ -0,0 +1,22 @@
+/**
+ * @license Copyright (c) 2003-2016, CKSource - Frederico Knabben. All rights reserved.
+ * For licensing, see LICENSE.md.
+ */
+
+'use strict';
+
+/**
+ * Returns a unique id. This id is a number (starting from 1) which will never get repeated on successive calls
+ * to this method.
+ *
+ * @function
+ * @memberOf utils
+ * @returns {Number} A number representing the id.
+ */
+export default ( () => {
+	let next = 1;
+
+	return () => {
+		return next++;
+	};
+} )();

+ 0 - 246
packages/ckeditor5-utils/src/utils.js

@@ -1,246 +0,0 @@
-/**
- * @license Copyright (c) 2003-2016, CKSource - Frederico Knabben. All rights reserved.
- * For licensing, see LICENSE.md.
- */
-
-'use strict';
-
-import isPlainObject from './lib/lodash/isPlainObject.js';
-
-/**
- * @namespace utils.utils
- */
-const utils = {
-	/**
-	 * Creates a spy function (ala Sinon.js) that can be used to inspect call to it.
-	 *
-	 * The following are the present features:
-	 *
-	 * * spy.called: property set to `true` if the function has been called at least once.
-	 *
-	 * @memberOf utils.utils
-	 * @returns {Function} The spy function.
-	 */
-	spy() {
-		return function spy() {
-			spy.called = true;
-		};
-	},
-
-	/**
-	 * Returns a unique id. This id is a number (starting from 1) which will never get repeated on successive calls
-	 * to this method.
-	 *
-	 * @function
-	 * @memberOf utils.utils
-	 * @returns {Number} A number representing the id.
-	 */
-	uid: ( () => {
-		let next = 1;
-
-		return () => {
-			return next++;
-		};
-	} )(),
-
-	/**
-	 * Checks if value implements iterator interface.
-	 *
-	 * @memberOf utils.utils
-	 * @param {*} value The value to check.
-	 * @returns {Boolean} True if value implements iterator interface.
-	 */
-	isIterable( value ) {
-		return !!( value && value[ Symbol.iterator ] );
-	},
-
-	/**
-	 * Compares how given arrays relate to each other. One array can be: same as another array, prefix of another array
-	 * or completely different. If arrays are different, first index at which they differ is returned. Otherwise,
-	 * a flag specifying the relation is returned. Flags are negative numbers, so whenever a number >= 0 is returned
-	 * it means that arrays differ.
-	 *
-	 *		compareArrays( [ 0, 2 ], [ 0, 2 ] );		// 'SAME'
-	 *		compareArrays( [ 0, 2 ], [ 0, 2, 1 ] );		// 'PREFIX'
-	 *		compareArrays( [ 0, 2 ], [ 0 ] );			// 'EXTENSION'
-	 *		compareArrays( [ 0, 2 ], [ 1, 2 ] );		// 0
-	 *		compareArrays( [ 0, 2 ], [ 0, 1 ] );		// 1
-	 *
-	 * @memberOf utils.utils
-	 * @param {Array} a Array that is compared.
-	 * @param {Array} b Array to compare with.
-	 * @returns {utils.ArrayRelation} How array `a` is related to `b`.
-	 */
-	compareArrays( a, b ) {
-		const minLen = Math.min( a.length, b.length );
-
-		for ( let i = 0; i < minLen; i++ ) {
-			if ( a[ i ] != b[ i ] ) {
-				// The arrays are different.
-				return i;
-			}
-		}
-
-		// Both arrays were same at all points.
-		if ( a.length == b.length ) {
-			// If their length is also same, they are the same.
-			return 'SAME';
-		} else if ( a.length < b.length ) {
-			// Compared array is shorter so it is a prefix of the other array.
-			return 'PREFIX';
-		} else {
-			// Compared array is longer so it is an extension of the other array.
-			return 'EXTENSION';
-		}
-	},
-
-	/**
-	 * Transforms object to map.
-	 *
-	 *		const map = utils.objectToMap( { 'foo': 1, 'bar': 2 } );
-	 *		map.get( 'foo' ); // 1
-	 *
-	 * @memberOf utils.utils
-	 * @param {Object} obj Object to transform.
-	 * @returns {Map} Map created from object.
-	 */
-	objectToMap( obj ) {
-		const map = new Map();
-
-		for ( let key in obj ) {
-			map.set( key, obj[ key ] );
-		}
-
-		return map;
-	},
-
-	/**
-	 * Transforms object or iterable to map. Iterable needs to be in the format acceptable by the `Map` constructor.
-	 *
-	 *		map = utils.toMap( { 'foo': 1, 'bar': 2 } );
-	 *		map = utils.toMap( [ [ 'foo', 1 ], [ 'bar', 2 ] ] );
-	 *		map = utils.toMap( anotherMap );
-	 *
-	 * @memberOf utils.utils
-	 * @param {Object|Iterable} data Object or iterable to transform.
-	 * @returns {Map} Map created from data.
-	 */
-	toMap( data ) {
-		if ( isPlainObject( data ) ) {
-			return utils.objectToMap( data );
-		} else {
-			return new Map( data );
-		}
-	},
-
-	/**
-	 * Checks whether given {Map}s are equal, that is has same size and same key-value pairs.
-	 *
-	 * @memberOf utils.utils
-	 * @returns {Boolean} `true` if given maps are equal, `false` otherwise.
-	 */
-	mapsEqual( mapA, mapB ) {
-		if ( mapA.size != mapB.size ) {
-			return false;
-		}
-
-		for ( let attr of mapA.entries() ) {
-			let valA = JSON.stringify( attr[ 1 ] );
-			let valB = JSON.stringify( mapB.get( attr[ 0 ] ) );
-
-			if ( valA !== valB ) {
-				return false;
-			}
-		}
-
-		return true;
-	},
-
-	/**
-	 * Returns `nth` (starts from `0` of course) item of an `iterable`.
-	 *
-	 * @memberOf utils.utils
-	 * @param {Number} index
-	 * @param {Iterable.<*>} iterable
-	 * @returns {*}
-	 */
-	nth( index, iterable ) {
-		for ( let item of iterable ) {
-			if ( index === 0 ) {
-				return item;
-			}
-			index -= 1;
-		}
-
-		return null;
-	},
-
-	/**
-	 * Returns the number of items return by the iterator.
-	 *
-	 *		utils.count( [ 1, 2, 3, 4, 5 ] ); // 5;
-	 *
-	 * @memberOf utils.utils
-	 * @param {Iterable.<*>} iterator Any iterator.
-	 * @returns {Number} Number of items returned by that iterator.
-	 */
-	count( iterator ) {
-		let count = 0;
-
-		for ( let _ of iterator ) { // jshint ignore:line
-			count++;
-		}
-
-		return count;
-	},
-
-	/**
-	 * Copies enumerable properties and symbols from the objects given as 2nd+ parameters to the
-	 * prototype of first object (a constructor).
-	 *
-	 *		class Editor {
-	 *			...
-	 *		}
-	 *
-	 *		const SomeMixin = {
-	 *			a() {
-	 *				return 'a';
-	 *			}
-	 *		};
-	 *
-	 *		utils.mix( Editor, SomeMixin, ... );
-	 *
-	 *		new Editor().a(); // -> 'a'
-	 *
-	 * Note: Properties which already exist in the base class will not be overriden.
-	 *
-	 * @memberOf utils.utils
-	 * @param {Function} [baseClass] Class which prototype will be extended.
-	 * @param {Object} [...mixins] Objects from which to get properties.
-	 */
-	mix( baseClass, ...mixins ) {
-		mixins.forEach( ( mixin ) => {
-			Object.getOwnPropertyNames( mixin ).concat( Object.getOwnPropertySymbols( mixin ) )
-				.forEach( ( key ) => {
-					if ( key in baseClass.prototype ) {
-						return;
-					}
-
-					const sourceDescriptor = Object.getOwnPropertyDescriptor( mixin, key );
-					sourceDescriptor.enumerable = false;
-
-					Object.defineProperty( baseClass.prototype, key, sourceDescriptor );
-				} );
-		} );
-	}
-};
-
-/**
- * An index at which arrays differ. If arrays are same at all indexes, it represents how arrays are related.
- * In this case, possible values are: `'SAME'`, `'PREFIX'` or `'EXTENSION'`.
- *
- * @memberOf utils.utils
- * @typedef {String|Number} utils.ArrayRelation
- */
-
-export default utils;

+ 1 - 8
packages/ckeditor5-utils/tests/collection.js

@@ -8,7 +8,6 @@
 import testUtils from '/tests/ckeditor5/_utils/utils.js';
 import testUtils from '/tests/ckeditor5/_utils/utils.js';
 import Collection from '/ckeditor5/utils/collection.js';
 import Collection from '/ckeditor5/utils/collection.js';
 import CKEditorError from '/ckeditor5/utils/ckeditorerror.js';
 import CKEditorError from '/ckeditor5/utils/ckeditorerror.js';
-import utils from '/ckeditor5/utils/utils.js';
 
 
 testUtils.createSinonSandbox();
 testUtils.createSinonSandbox();
 
 
@@ -143,12 +142,6 @@ describe( 'Collection', () => {
 			'should not override item under an existing id in case of a collision ' +
 			'should not override item under an existing id in case of a collision ' +
 			'between existing items and one with an automatically generated id',
 			'between existing items and one with an automatically generated id',
 			() => {
 			() => {
-				let nextUid = 0;
-
-				testUtils.sinon.stub( utils, 'uid', () => {
-					return nextUid++;
-				} );
-
 				collection.add( getItem( '0' ) );
 				collection.add( getItem( '0' ) );
 				collection.add( getItem( '1' ) );
 				collection.add( getItem( '1' ) );
 				collection.add( getItem( '2' ) );
 				collection.add( getItem( '2' ) );
@@ -157,7 +150,7 @@ describe( 'Collection', () => {
 
 
 				collection.add( item );
 				collection.add( item );
 
 
-				expect( item ).to.have.property( 'id', '3' );
+				expect( item.id ).to.be.above( '3' );
 			}
 			}
 		);
 		);
 
 

+ 48 - 0
packages/ckeditor5-utils/tests/comparearrays.js

@@ -0,0 +1,48 @@
+/**
+ * @license Copyright (c) 2003-2016, CKSource - Frederico Knabben. All rights reserved.
+ * For licensing, see LICENSE.md.
+ */
+
+'use strict';
+
+import compareArrays from '/ckeditor5/utils/comparearrays.js';
+
+describe( 'utils', () => {
+	describe( 'compareArrays', () => {
+		it( 'should return SAME flag, when arrays are same', () => {
+			let a = [ 'abc', 0, 3 ];
+			let b = [ 'abc', 0, 3 ];
+
+			let result = compareArrays( a, b );
+
+			expect( result ).to.equal( 'SAME' );
+		} );
+
+		it( 'should return PREFIX flag, when all n elements of first array are same as n first elements of the second array', () => {
+			let a = [ 'abc', 0 ];
+			let b = [ 'abc', 0, 3 ];
+
+			let result = compareArrays( a, b );
+
+			expect( result ).to.equal( 'PREFIX' );
+		} );
+
+		it( 'should return EXTENSION flag, when n first elements of first array are same as all elements of the second array', () => {
+			let a = [ 'abc', 0, 3 ];
+			let b = [ 'abc', 0 ];
+
+			let result = compareArrays( a, b );
+
+			expect( result ).to.equal( 'EXTENSION' );
+		} );
+
+		it( 'should return index on which arrays differ, when arrays are not the same', () => {
+			let a = [ 'abc', 0, 3 ];
+			let b = [ 'abc', 1, 3 ];
+
+			let result = compareArrays( a, b );
+
+			expect( result ).to.equal( 1 );
+		} );
+	} );
+} );

+ 17 - 0
packages/ckeditor5-utils/tests/count.js

@@ -0,0 +1,17 @@
+/**
+ * @license Copyright (c) 2003-2016, CKSource - Frederico Knabben. All rights reserved.
+ * For licensing, see LICENSE.md.
+ */
+
+'use strict';
+
+import count from '/ckeditor5/utils/count.js';
+
+describe( 'utils', () => {
+	describe( 'count', () => {
+		it( 'should returns number of editable items', () => {
+			const totalNumber = count( [ 1, 2, 3, 4, 5 ] );
+			expect( totalNumber ).to.equal( 5 );
+		} );
+	} );
+} );

+ 50 - 0
packages/ckeditor5-utils/tests/isIterable.js

@@ -0,0 +1,50 @@
+/**
+ * @license Copyright (c) 2003-2016, CKSource - Frederico Knabben. All rights reserved.
+ * For licensing, see LICENSE.md.
+ */
+
+'use strict';
+
+import isIterable from '/ckeditor5/utils/isiterable.js';
+
+describe( 'utils', () => {
+	describe( 'isIterable', () => {
+		it( 'should be true for string', () => {
+			let string = 'foo';
+
+			expect( isIterable( string ) ).to.be.true;
+		} );
+
+		it( 'should be true for arrays', () => {
+			let array = [ 1, 2, 3 ];
+
+			expect( isIterable( array ) ).to.be.true;
+		} );
+
+		it( 'should be true for iterable classes', () => {
+			class IterableClass {
+				constructor() {
+					this.array = [ 1, 2, 3 ];
+				}
+
+				[ Symbol.iterator ]() {
+					return this.array[ Symbol.iterator ]();
+				}
+			}
+
+			let instance = new IterableClass();
+
+			expect( isIterable( instance ) ).to.be.true;
+		} );
+
+		it( 'should be false for not iterable objects', () => {
+			let notIterable = { foo: 'bar' };
+
+			expect( isIterable( notIterable ) ).to.be.false;
+		} );
+
+		it( 'should be false for undefined', () => {
+			expect( isIterable() ).to.be.false;
+		} );
+	} );
+} );

+ 25 - 0
packages/ckeditor5-utils/tests/mapsequal.js

@@ -0,0 +1,25 @@
+/**
+ * @license Copyright (c) 2003-2016, CKSource - Frederico Knabben. All rights reserved.
+ * For licensing, see LICENSE.md.
+ */
+
+'use strict';
+
+import mapsEqual from '/ckeditor5/utils/mapsequal.js';
+
+describe( 'utils', () => {
+	describe( 'mapsEqual', () => {
+		it( 'should return true if maps have exactly same entries (order of adding does not matter)', () => {
+			let mapA = new Map();
+			let mapB = new Map();
+
+			mapA.set( 'foo', 'bar' );
+			mapA.set( 'abc', 'xyz' );
+
+			mapB.set( 'abc', 'xyz' );
+			mapB.set( 'foo', 'bar' );
+
+			expect( mapsEqual( mapA, mapB ) ).to.be.true;
+		} );
+	} );
+} );

+ 157 - 0
packages/ckeditor5-utils/tests/mix.js

@@ -0,0 +1,157 @@
+/**
+ * @license Copyright (c) 2003-2016, CKSource - Frederico Knabben. All rights reserved.
+ * For licensing, see LICENSE.md.
+ */
+
+'use strict';
+
+import mix from '/ckeditor5/utils/mix.js';
+
+describe( 'utils', () => {
+	describe( 'mix', () => {
+		const MixinA = {
+			a() {
+				return 'a';
+			}
+		};
+		const MixinB = {
+			b() {
+				return 'b';
+			}
+		};
+
+		it( 'mixes 2nd+ argument\'s properties into the first class', () => {
+			class Foo {}
+			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 {}
+			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() {}
+			}
+
+			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;
+				}
+			};
+
+			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
+
+			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' );
+		} );
+
+		it( 'does not copy already existing properties', () => {
+			class Foo {
+				a() {
+					return 'foo';
+				}
+			}
+			mix( Foo, MixinA, MixinB );
+
+			const foo = new Foo();
+
+			expect( foo.a() ).to.equal( 'foo' );
+			expect( foo.b() ).to.equal( 'b' );
+		} );
+
+		it( 'does not copy already existing properties - properties deep in the proto chain', () => {
+			class Foo {
+				a() {
+					return 'foo';
+				}
+			}
+			class Bar extends Foo {}
+
+			mix( Bar, MixinA, MixinB );
+
+			const bar = new Bar();
+
+			expect( bar.a() ).to.equal( 'foo' );
+			expect( bar.b() ).to.equal( 'b' );
+		} );
+	} );
+} );

+ 38 - 0
packages/ckeditor5-utils/tests/nth.js

@@ -0,0 +1,38 @@
+/**
+ * @license Copyright (c) 2003-2016, CKSource - Frederico Knabben. All rights reserved.
+ * For licensing, see LICENSE.md.
+ */
+
+'use strict';
+
+import nth from '/ckeditor5/utils/nth.js';
+
+describe( 'utils', () => {
+	describe( 'nth', () => {
+		it( 'should return 0th item', () => {
+			expect( nth( 0, getIterator() ) ).to.equal( 11 );
+		} );
+
+		it( 'should return the last item', () => {
+			expect( nth( 2, getIterator() ) ).to.equal( 33 );
+		} );
+
+		it( 'should return null if out of range (bottom)', () => {
+			expect( nth( -1, getIterator() ) ).to.be.null;
+		} );
+
+		it( 'should return null if out of range (top)', () => {
+			expect( nth( 3, getIterator() ) ).to.be.null;
+		} );
+
+		it( 'should return null if iterator is empty', () => {
+			expect( nth( 0, [] ) ).to.be.null;
+		} );
+
+		function *getIterator() {
+			yield 11;
+			yield 22;
+			yield 33;
+		}
+	} );
+} );

+ 2 - 2
packages/ckeditor5-utils/tests/observablemixin.js

@@ -11,7 +11,7 @@ import ObservableMixin from '/ckeditor5/utils/observablemixin.js';
 import EmitterMixin from '/ckeditor5/utils/emittermixin.js';
 import EmitterMixin from '/ckeditor5/utils/emittermixin.js';
 import EventInfo from '/ckeditor5/utils/eventinfo.js';
 import EventInfo from '/ckeditor5/utils/eventinfo.js';
 import CKEditorError from '/ckeditor5/utils/ckeditorerror.js';
 import CKEditorError from '/ckeditor5/utils/ckeditorerror.js';
-import utils from '/ckeditor5/utils/utils.js';
+import mix from '/ckeditor5/utils/mix.js';
 
 
 const assertBinding = utilsTestUtils.assertBinding;
 const assertBinding = utilsTestUtils.assertBinding;
 
 
@@ -39,7 +39,7 @@ describe( 'Observable', () => {
 			}
 			}
 		}
 		}
 	}
 	}
-	utils.mix( Observable, ObservableMixin );
+	mix( Observable, ObservableMixin );
 
 
 	let Car, car;
 	let Car, car;
 
 

+ 28 - 0
packages/ckeditor5-utils/tests/spy.js

@@ -0,0 +1,28 @@
+/**
+ * @license Copyright (c) 2003-2016, CKSource - Frederico Knabben. All rights reserved.
+ * For licensing, see LICENSE.md.
+ */
+
+'use strict';
+
+import spy from '/ckeditor5/utils/spy.js';
+
+describe( 'utils', () => {
+	describe( 'spy', () => {
+		it( 'should not have `called` after creation', () => {
+			let fn = spy();
+
+			expect( fn.called ).to.not.be.true();
+		} );
+
+		it( 'should register calls', () => {
+			let fn1 = spy();
+			let fn2 = spy();
+
+			fn1();
+
+			expect( fn1.called ).to.be.true();
+			expect( fn2.called ).to.not.be.true();
+		} );
+	} );
+} );

+ 39 - 0
packages/ckeditor5-utils/tests/tomap.js

@@ -0,0 +1,39 @@
+/**
+ * @license Copyright (c) 2003-2016, CKSource - Frederico Knabben. All rights reserved.
+ * For licensing, see LICENSE.md.
+ */
+
+'use strict';
+
+import toMap from '/ckeditor5/utils/tomap.js';
+import count from '/ckeditor5/utils/count.js';
+
+describe( 'utils', () => {
+	describe( 'toMap', () => {
+		it( 'should create map from object', () => {
+			const map = toMap( { foo: 1, bar: 2 } );
+
+			expect( count( map ) ).to.equal( 2 );
+			expect( map.get( 'foo' ) ).to.equal( 1 );
+			expect( map.get( 'bar' ) ).to.equal( 2 );
+		} );
+
+		it( 'should create map from iterator', () => {
+			const map = toMap( [ [ 'foo', 1 ], [ 'bar', 2 ] ] );
+
+			expect( count( map ) ).to.equal( 2 );
+			expect( map.get( 'foo' ) ).to.equal( 1 );
+			expect( map.get( 'bar' ) ).to.equal( 2 );
+		} );
+
+		it( 'should create map from another map', () => {
+			const data = new Map( [ [ 'foo', 1 ], [ 'bar', 2 ] ] );
+
+			const map = toMap( data );
+
+			expect( count( map ) ).to.equal( 2 );
+			expect( map.get( 'foo' ) ).to.equal( 1 );
+			expect( map.get( 'bar' ) ).to.equal( 2 );
+		} );
+	} );
+} );

+ 22 - 0
packages/ckeditor5-utils/tests/uid.js

@@ -0,0 +1,22 @@
+/**
+ * @license Copyright (c) 2003-2016, CKSource - Frederico Knabben. All rights reserved.
+ * For licensing, see LICENSE.md.
+ */
+
+'use strict';
+
+import uid from '/ckeditor5/utils/uid.js';
+
+describe( 'utils', () => {
+	describe( 'uid', () => {
+		it( 'should return different ids', () => {
+			let id1 = uid();
+			let id2 = uid();
+			let id3 = uid();
+
+			expect( id1 ).to.be.a( 'number' );
+			expect( id2 ).to.be.a( 'number' ).to.not.equal( id1 ).to.not.equal( id3 );
+			expect( id3 ).to.be.a( 'number' ).to.not.equal( id1 ).to.not.equal( id2 );
+		} );
+	} );
+} );

+ 0 - 345
packages/ckeditor5-utils/tests/utils.js

@@ -1,345 +0,0 @@
-/**
- * @license Copyright (c) 2003-2016, CKSource - Frederico Knabben. All rights reserved.
- * For licensing, see LICENSE.md.
- */
-
-'use strict';
-
-import utils from '/ckeditor5/utils/utils.js';
-
-const count = utils.count;
-
-describe( 'utils', () => {
-	describe( 'spy', () => {
-		it( 'should not have `called` after creation', () => {
-			let spy = utils.spy();
-
-			expect( spy.called ).to.not.be.true();
-		} );
-
-		it( 'should register calls', () => {
-			let fn1 = utils.spy();
-			let fn2 = utils.spy();
-
-			fn1();
-
-			expect( fn1.called ).to.be.true();
-			expect( fn2.called ).to.not.be.true();
-		} );
-	} );
-
-	describe( 'uid', () => {
-		it( 'should return different ids', () => {
-			let id1 = utils.uid();
-			let id2 = utils.uid();
-			let id3 = utils.uid();
-
-			expect( id1 ).to.be.a( 'number' );
-			expect( id2 ).to.be.a( 'number' ).to.not.equal( id1 ).to.not.equal( id3 );
-			expect( id3 ).to.be.a( 'number' ).to.not.equal( id1 ).to.not.equal( id2 );
-		} );
-	} );
-
-	describe( 'isIterable', () => {
-		it( 'should be true for string', () => {
-			let string = 'foo';
-
-			expect( utils.isIterable( string ) ).to.be.true;
-		} );
-
-		it( 'should be true for arrays', () => {
-			let array = [ 1, 2, 3 ];
-
-			expect( utils.isIterable( array ) ).to.be.true;
-		} );
-
-		it( 'should be true for iterable classes', () => {
-			class IterableClass {
-				constructor() {
-					this.array = [ 1, 2, 3 ];
-				}
-
-				[ Symbol.iterator ]() {
-					return this.array[ Symbol.iterator ]();
-				}
-			}
-
-			let instance = new IterableClass();
-
-			expect( utils.isIterable( instance ) ).to.be.true;
-		} );
-
-		it( 'should be false for not iterable objects', () => {
-			let notIterable = { foo: 'bar' };
-
-			expect( utils.isIterable( notIterable ) ).to.be.false;
-		} );
-
-		it( 'should be false for undefined', () => {
-			expect( utils.isIterable() ).to.be.false;
-		} );
-	} );
-
-	describe( 'compareArrays', () => {
-		it( 'should return SAME flag, when arrays are same', () => {
-			let a = [ 'abc', 0, 3 ];
-			let b = [ 'abc', 0, 3 ];
-
-			let result = utils.compareArrays( a, b );
-
-			expect( result ).to.equal( 'SAME' );
-		} );
-
-		it( 'should return PREFIX flag, when all n elements of first array are same as n first elements of the second array', () => {
-			let a = [ 'abc', 0 ];
-			let b = [ 'abc', 0, 3 ];
-
-			let result = utils.compareArrays( a, b );
-
-			expect( result ).to.equal( 'PREFIX' );
-		} );
-
-		it( 'should return EXTENSION flag, when n first elements of first array are same as all elements of the second array', () => {
-			let a = [ 'abc', 0, 3 ];
-			let b = [ 'abc', 0 ];
-
-			let result = utils.compareArrays( a, b );
-
-			expect( result ).to.equal( 'EXTENSION' );
-		} );
-
-		it( 'should return index on which arrays differ, when arrays are not the same', () => {
-			let a = [ 'abc', 0, 3 ];
-			let b = [ 'abc', 1, 3 ];
-
-			let result = utils.compareArrays( a, b );
-
-			expect( result ).to.equal( 1 );
-		} );
-	} );
-
-	describe( 'toMap', () => {
-		it( 'should create map from object', () => {
-			const map = utils.toMap( { foo: 1, bar: 2 } );
-
-			expect( count( map ) ).to.equal( 2 );
-			expect( map.get( 'foo' ) ).to.equal( 1 );
-			expect( map.get( 'bar' ) ).to.equal( 2 );
-		} );
-
-		it( 'should create map from iterator', () => {
-			const map = utils.toMap( [ [ 'foo', 1 ], [ 'bar', 2 ] ] );
-
-			expect( count( map ) ).to.equal( 2 );
-			expect( map.get( 'foo' ) ).to.equal( 1 );
-			expect( map.get( 'bar' ) ).to.equal( 2 );
-		} );
-
-		it( 'should create map from another map', () => {
-			const data = new Map( [ [ 'foo', 1 ], [ 'bar', 2 ] ] );
-
-			const map = utils.toMap( data );
-
-			expect( count( map ) ).to.equal( 2 );
-			expect( map.get( 'foo' ) ).to.equal( 1 );
-			expect( map.get( 'bar' ) ).to.equal( 2 );
-		} );
-	} );
-
-	describe( 'mapsEqual', () => {
-		it( 'should return true if maps have exactly same entries (order of adding does not matter)', () => {
-			let mapA = new Map();
-			let mapB = new Map();
-
-			mapA.set( 'foo', 'bar' );
-			mapA.set( 'abc', 'xyz' );
-
-			mapB.set( 'abc', 'xyz' );
-			mapB.set( 'foo', 'bar' );
-
-			expect( utils.mapsEqual( mapA, mapB ) ).to.be.true;
-		} );
-	} );
-
-	describe( 'nth', () => {
-		it( 'should return 0th item', () => {
-			expect( utils.nth( 0, getIterator() ) ).to.equal( 11 );
-		} );
-
-		it( 'should return the last item', () => {
-			expect( utils.nth( 2, getIterator() ) ).to.equal( 33 );
-		} );
-
-		it( 'should return null if out of range (bottom)', () => {
-			expect( utils.nth( -1, getIterator() ) ).to.be.null;
-		} );
-
-		it( 'should return null if out of range (top)', () => {
-			expect( utils.nth( 3, getIterator() ) ).to.be.null;
-		} );
-
-		it( 'should return null if iterator is empty', () => {
-			expect( utils.nth( 0, [] ) ).to.be.null;
-		} );
-
-		function *getIterator() {
-			yield 11;
-			yield 22;
-			yield 33;
-		}
-	} );
-
-	describe( 'count', () => {
-		it( 'should returns number of editable items', () => {
-			const count = utils.count( [ 1, 2, 3, 4, 5 ] );
-			expect( count ).to.equal( 5 );
-		} );
-	} );
-
-	describe( 'mix', () => {
-		const MixinA = {
-			a() {
-				return 'a';
-			}
-		};
-		const MixinB = {
-			b() {
-				return 'b';
-			}
-		};
-
-		it( 'mixes 2nd+ argument\'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' );
-		} );
-
-		it( 'does not copy already existing properties', () => {
-			class Foo {
-				a() {
-					return 'foo';
-				}
-			}
-			utils.mix( Foo, MixinA, MixinB );
-
-			const foo = new Foo();
-
-			expect( foo.a() ).to.equal( 'foo' );
-			expect( foo.b() ).to.equal( 'b' );
-		} );
-
-		it( 'does not copy already existing properties - properties deep in the proto chain', () => {
-			class Foo {
-				a() {
-					return 'foo';
-				}
-			}
-			class Bar extends Foo {}
-
-			utils.mix( Bar, MixinA, MixinB );
-
-			const bar = new Bar();
-
-			expect( bar.a() ).to.equal( 'foo' );
-			expect( bar.b() ).to.equal( 'b' );
-		} );
-	} );
-} );