Browse Source

Tests: Unit Tests for Animation (#25409)

* Update AnimationAction.tests.js

Explicit block scope for variables used in tests.
Stub missing member tests.

* Update AnimationClip.tests.js

AnimationClip can be instanciated
AnimationClip can be named
Stub missing member tests.

* Update AnimationMixer.tests.js

AnimationMixer extends from EventDispatcher
Stub missing member tests.

* Update AnimationObjectGroup.tests.js

AnimationObjectGroup can be instanciated
AnimationObjectGroup.isAnimationObjectGroup should be true
Explicit block scope for variables used in tests.
Stub missing member tests.

* Update AnimationUtils.tests.js

Stub missing member tests.

* Update KeyframeTrack.tests.js

Stub missing member tests.

* Update PropertyBinding.tests.js

Explicit block scope for variables used in tests.

* Update PropertyMixer.tests.js

Stub missing member tests.

* Update BooleanKeyframeTrack.tests.js

BooleanKeyframeTrack extends from KeyframeTrack

* Update ColorKeyframeTrack.tests.js

ColorKeyframeTrack extends from KeyframeTrack

* Update NumberKeyframeTrack.tests.js

NumberKeyframeTrack extends from KeyframeTrack

* Update QuaternionKeyframeTrack.tests.js

QuaternionKeyframeTrack extends from KeyframeTrack

* Update StringKeyframeTrack.tests.js

StringKeyframeTrack extends from KeyframeTrack

* Update VectorKeyframeTrack.tests.js

VectorKeyframeTrack extends from KeyframeTrack

* Separate test subject

Separate the first import to clearly mark the test subject.

* Update KeyframeTrack.tests.js

Explicit block scope for variables used in tests.

* Update AnimationAction.tests.js

Split setEffectiveWeight into 3 functional tests and resolve the variable block scope issue at the same time.  At the moment, trying to minimize changes to working tests.
Ed Preston 2 years ago
parent
commit
672b8f2a3f

+ 125 - 50
test/unit/src/animation/AnimationAction.tests.js

@@ -1,6 +1,7 @@
 /* global QUnit */
 
 import { AnimationAction } from '../../../../src/animation/AnimationAction.js';
+
 import { AnimationMixer } from '../../../../src/animation/AnimationMixer.js';
 import { AnimationClip } from '../../../../src/animation/AnimationClip.js';
 import { NumberKeyframeTrack } from '../../../../src/animation/tracks/NumberKeyframeTrack.js';
@@ -10,12 +11,12 @@ import { LoopOnce, LoopRepeat, LoopPingPong } from '../../../../src/constants.js
 
 function createAnimation() {
 
-	var root = new Object3D();
-	var mixer = new AnimationMixer( root );
-	var track = new NumberKeyframeTrack( '.rotation[x]', [ 0, 1000 ], [ 0, 360 ] );
-	var clip = new AnimationClip( 'clip1', 1000, [ track ] );
+	const root = new Object3D();
+	const mixer = new AnimationMixer( root );
+	const track = new NumberKeyframeTrack( '.rotation[x]', [ 0, 1000 ], [ 0, 360 ] );
+	const clip = new AnimationClip( 'clip1', 1000, [ track ] );
 
-	var animationAction = mixer.clipAction( clip );
+	const animationAction = mixer.clipAction( clip );
 	return {
 		root: root,
 		mixer: mixer,
@@ -28,15 +29,15 @@ function createAnimation() {
 
 function createTwoAnimations() {
 
-	var root = new Object3D();
-	var mixer = new AnimationMixer( root );
-	var track = new NumberKeyframeTrack( '.rotation[x]', [ 0, 1000 ], [ 0, 360 ] );
-	var clip = new AnimationClip( 'clip1', 1000, [ track ] );
-	var animationAction = mixer.clipAction( clip );
+	const root = new Object3D();
+	const mixer = new AnimationMixer( root );
+	const track = new NumberKeyframeTrack( '.rotation[x]', [ 0, 1000 ], [ 0, 360 ] );
+	const clip = new AnimationClip( 'clip1', 1000, [ track ] );
+	const animationAction = mixer.clipAction( clip );
 
-	var track2 = new NumberKeyframeTrack( '.rotation[y]', [ 0, 1000 ], [ 0, 360 ] );
-	var clip2 = new AnimationClip( 'clip2', 1000, [ track ] );
-	var animationAction2 = mixer.clipAction( clip2 );
+	const track2 = new NumberKeyframeTrack( '.rotation[y]', [ 0, 1000 ], [ 0, 360 ] );
+	const clip2 = new AnimationClip( 'clip2', 1000, [ track ] );
+	const animationAction2 = mixer.clipAction( clip2 );
 
 	return {
 		root: root,
@@ -59,22 +60,89 @@ export default QUnit.module( 'Animation', () => {
 		// INSTANCING
 		QUnit.test( 'Instancing', ( assert ) => {
 
-			var mixer = new AnimationMixer();
-			var clip = new AnimationClip( 'nonname', - 1, [] );
+			const mixer = new AnimationMixer();
+			const clip = new AnimationClip( 'nonname', - 1, [] );
 
-			var animationAction = new AnimationAction( mixer, clip );
+			const animationAction = new AnimationAction( mixer, clip );
 			assert.ok( animationAction, 'animationAction instanciated' );
 
 		} );
 
+		// PROPERTIES
+		QUnit.todo( 'blendMode', ( assert ) => {
+
+			assert.ok( false, 'everything\'s gonna be alright' );
+
+		} );
+
+		QUnit.todo( 'loop', ( assert ) => {
+
+			assert.ok( false, 'everything\'s gonna be alright' );
+
+		} );
+
+		QUnit.todo( 'time', ( assert ) => {
+
+			assert.ok( false, 'everything\'s gonna be alright' );
+
+		} );
+
+		QUnit.todo( 'timeScale', ( assert ) => {
+
+			assert.ok( false, 'everything\'s gonna be alright' );
+
+		} );
+
+		QUnit.todo( 'weight', ( assert ) => {
+
+			assert.ok( false, 'everything\'s gonna be alright' );
+
+		} );
+
+		QUnit.todo( 'repetitions', ( assert ) => {
+
+			assert.ok( false, 'everything\'s gonna be alright' );
+
+		} );
+
+		QUnit.todo( 'paused', ( assert ) => {
+
+			assert.ok( false, 'everything\'s gonna be alright' );
+
+		} );
+
+		QUnit.todo( 'enabled', ( assert ) => {
+
+			assert.ok( false, 'everything\'s gonna be alright' );
+
+		} );
+
+		QUnit.todo( 'clampWhenFinished', ( assert ) => {
+
+			assert.ok( false, 'everything\'s gonna be alright' );
+
+		} );
+
+		QUnit.todo( 'zeroSlopeAtStart', ( assert ) => {
+
+			assert.ok( false, 'everything\'s gonna be alright' );
+
+		} );
+
+		QUnit.todo( 'zeroSlopeAtEnd', ( assert ) => {
+
+			assert.ok( false, 'everything\'s gonna be alright' );
+
+		} );
+
 		// PUBLIC STUFF
 		QUnit.test( 'play', ( assert ) => {
 
-			var { mixer, animationAction } = createAnimation();
-			var animationAction2 = animationAction.play();
+			const { mixer, animationAction } = createAnimation();
+			const animationAction2 = animationAction.play();
 			assert.equal( animationAction, animationAction2, 'AnimationAction.play can be chained.' );
 
-			var UserException = function () {
+			const UserException = function () {
 
 				this.message = 'AnimationMixer must activate AnimationAction on play.';
 
@@ -100,11 +168,11 @@ export default QUnit.module( 'Animation', () => {
 
 		QUnit.test( 'stop', ( assert ) => {
 
-			var { mixer, animationAction } = createAnimation();
-			var animationAction2 = animationAction.stop();
+			const { mixer, animationAction } = createAnimation();
+			const animationAction2 = animationAction.stop();
 			assert.equal( animationAction, animationAction2, 'AnimationAction.stop can be chained.' );
 
-			var UserException = function () {
+			const UserException = function () {
 
 				this.message = 'AnimationMixer must deactivate AnimationAction on stop.';
 
@@ -130,8 +198,8 @@ export default QUnit.module( 'Animation', () => {
 
 		QUnit.test( 'reset', ( assert ) => {
 
-			var { animationAction } = createAnimation();
-			var animationAction2 = animationAction.stop();
+			const { animationAction } = createAnimation();
+			const animationAction2 = animationAction.stop();
 			assert.equal( animationAction, animationAction2, 'AnimationAction.reset can be chained.' );
 			assert.equal( animationAction2.paused, false, 'AnimationAction.reset() sets paused false' );
 			assert.equal( animationAction2.enabled, true, 'AnimationAction.reset() sets enabled true' );
@@ -143,7 +211,7 @@ export default QUnit.module( 'Animation', () => {
 
 		QUnit.test( 'isRunning', ( assert ) => {
 
-			var { animationAction } = createAnimation();
+			const { animationAction } = createAnimation();
 			assert.notOk( animationAction.isRunning(), 'When an animation is just made, it is not running.' );
 			animationAction.play();
 			assert.ok( animationAction.isRunning(), 'When an animation is started, it is running.' );
@@ -162,7 +230,7 @@ export default QUnit.module( 'Animation', () => {
 
 		QUnit.test( 'isScheduled', ( assert ) => {
 
-			var { mixer, animationAction } = createAnimation();
+			const { mixer, animationAction } = createAnimation();
 			assert.notOk( animationAction.isScheduled(), 'When an animation is just made, it is not scheduled.' );
 			animationAction.play();
 			assert.ok( animationAction.isScheduled(), 'When an animation is started, it is scheduled.' );
@@ -176,7 +244,7 @@ export default QUnit.module( 'Animation', () => {
 
 		QUnit.test( 'startAt', ( assert ) => {
 
-			var { mixer, animationAction } = createAnimation();
+			const { mixer, animationAction } = createAnimation();
 			animationAction.startAt( 2 );
 			animationAction.play();
 			assert.notOk( animationAction.isRunning(), 'When an animation is started at a specific time, it is not running.' );
@@ -196,7 +264,7 @@ export default QUnit.module( 'Animation', () => {
 
 		QUnit.test( 'setLoop LoopOnce', ( assert ) => {
 
-			var { mixer, animationAction } = createAnimation();
+			const { mixer, animationAction } = createAnimation();
 			animationAction.setLoop( LoopOnce );
 			animationAction.play();
 			assert.ok( animationAction.isRunning(), 'When an animation is started, it is running.' );
@@ -211,7 +279,7 @@ export default QUnit.module( 'Animation', () => {
 
 		QUnit.test( 'setLoop LoopRepeat', ( assert ) => {
 
-			var { root, mixer, animationAction } = createAnimation();
+			const { root, mixer, animationAction } = createAnimation();
 			animationAction.setLoop( LoopRepeat, 3 );
 			animationAction.play();
 			assert.ok( animationAction.isRunning(), 'When an animation is started, it is running.' );
@@ -232,7 +300,7 @@ export default QUnit.module( 'Animation', () => {
 
 		QUnit.test( 'setLoop LoopPingPong', ( assert ) => {
 
-			var { root, mixer, animationAction } = createAnimation();
+			const { root, mixer, animationAction } = createAnimation();
 			animationAction.setLoop( LoopPingPong, 3 );
 			animationAction.play();
 			assert.ok( animationAction.isRunning(), 'When an animation is started, it is running.' );
@@ -253,20 +321,26 @@ export default QUnit.module( 'Animation', () => {
 
 		QUnit.test( 'setEffectiveWeight', ( assert ) => {
 
-			var { animationAction } = createAnimation();
+			const { animationAction } = createAnimation();
 			assert.equal( animationAction.getEffectiveWeight(), 1, 'When an animation is created, EffectiveWeight is 1.' );
 			animationAction.setEffectiveWeight( 0.3 );
 			assert.equal( animationAction.getEffectiveWeight(), 0.3, 'When EffectiveWeight is set to 0.3 , EffectiveWeight is 0.3.' );
 
+		} );
 
-			var { animationAction } = createAnimation();
+		QUnit.test( 'setEffectiveWeight - disabled', ( assert ) => {
+
+			const { animationAction } = createAnimation();
 			assert.equal( animationAction.getEffectiveWeight(), 1, 'When an animation is created, EffectiveWeight is 1.' );
 			animationAction.enabled = false;
 			animationAction.setEffectiveWeight( 0.3 );
 			assert.equal( animationAction.getEffectiveWeight(), 0, 'When EffectiveWeight is set to 0.3 when disabled , EffectiveWeight is 0.' );
 
+		} );
+
+		QUnit.test( 'setEffectiveWeight - over duration', ( assert ) => {
 
-			var { root, mixer, animationAction } = createAnimation();
+			const { root, mixer, animationAction } = createAnimation();
 			animationAction.setEffectiveWeight( 0.5 );
 			animationAction.play();
 			mixer.update( 500 );
@@ -278,13 +352,13 @@ export default QUnit.module( 'Animation', () => {
 
 		QUnit.test( 'getEffectiveWeight', ( assert ) => {
 
-			var { animationAction } = createAnimation();
+			let { animationAction } = createAnimation();
 			assert.equal( animationAction.getEffectiveWeight(), 1, 'When an animation is created, EffectiveWeight is 1.' );
 			animationAction.setEffectiveWeight( 0.3 );
 			assert.equal( animationAction.getEffectiveWeight(), 0.3, 'When EffectiveWeight is set to 0.3 , EffectiveWeight is 0.3.' );
 
 
-			var { animationAction } = createAnimation();
+			( { animationAction } = createAnimation() );
 			assert.equal( animationAction.getEffectiveWeight(), 1, 'When an animation is created, EffectiveWeight is 1.' );
 			animationAction.enabled = false;
 			animationAction.setEffectiveWeight( 0.3 );
@@ -294,7 +368,7 @@ export default QUnit.module( 'Animation', () => {
 
 		QUnit.test( 'fadeIn', ( assert ) => {
 
-			var { mixer, animationAction } = createAnimation();
+			const { mixer, animationAction } = createAnimation();
 			animationAction.fadeIn( 1000 );
 			animationAction.play();
 			assert.equal( animationAction.getEffectiveWeight(), 1, 'When an animation fadeIn is started, EffectiveWeight is 1.' );
@@ -311,7 +385,7 @@ export default QUnit.module( 'Animation', () => {
 
 		QUnit.test( 'fadeOut', ( assert ) => {
 
-			var { mixer, animationAction } = createAnimation();
+			const { mixer, animationAction } = createAnimation();
 			animationAction.fadeOut( 1000 );
 			animationAction.play();
 			assert.equal( animationAction.getEffectiveWeight(), 1, 'When an animation fadeOut is started, EffectiveWeight is 1.' );
@@ -328,7 +402,7 @@ export default QUnit.module( 'Animation', () => {
 
 		QUnit.test( 'crossFadeFrom', ( assert ) => {
 
-			var { mixer, animationAction, animationAction2 } = createTwoAnimations();
+			const { mixer, animationAction, animationAction2 } = createTwoAnimations();
 			animationAction.crossFadeFrom( animationAction2, 1000, false );
 			animationAction.play();
 			animationAction2.play();
@@ -351,7 +425,7 @@ export default QUnit.module( 'Animation', () => {
 
 		QUnit.test( 'crossFadeTo', ( assert ) => {
 
-			var { mixer, animationAction, animationAction2 } = createTwoAnimations();
+			const { mixer, animationAction, animationAction2 } = createTwoAnimations();
 			animationAction2.crossFadeTo( animationAction, 1000, false );
 			animationAction.play();
 			animationAction2.play();
@@ -422,36 +496,37 @@ export default QUnit.module( 'Animation', () => {
 
 		QUnit.test( 'getMixer', ( assert ) => {
 
-			var { mixer, animationAction } = createAnimation();
-			var mixer2 = animationAction.getMixer();
+			const { mixer, animationAction } = createAnimation();
+			const mixer2 = animationAction.getMixer();
 			assert.equal( mixer, mixer2, 'mixer should be returned by getMixer.' );
 
 		} );
 
 		QUnit.test( 'getClip', ( assert ) => {
 
-			var { clip, animationAction } = createAnimation();
-			var clip2 = animationAction.getClip();
+			const { clip, animationAction } = createAnimation();
+			const clip2 = animationAction.getClip();
 			assert.equal( clip, clip2, 'clip should be returned by getClip.' );
 
 		} );
 
 		QUnit.test( 'getRoot', ( assert ) => {
 
-			var { root, animationAction } = createAnimation();
-			var root2 = animationAction.getRoot();
+			const { root, animationAction } = createAnimation();
+			const root2 = animationAction.getRoot();
 			assert.equal( root, root2, 'root should be returned by getRoot.' );
 
 		} );
 
+		// OTHERS
 		QUnit.test( 'StartAt when already executed once', ( assert ) => {
 
-			var root = new Object3D();
-			var mixer = new AnimationMixer( root );
-			var track = new NumberKeyframeTrack( '.rotation[x]', [ 0, 750 ], [ 0, 270 ] );
-			var clip = new AnimationClip( 'clip1', 750, [ track ] );
+			const root = new Object3D();
+			const mixer = new AnimationMixer( root );
+			const track = new NumberKeyframeTrack( '.rotation[x]', [ 0, 750 ], [ 0, 270 ] );
+			const clip = new AnimationClip( 'clip1', 750, [ track ] );
 
-			var animationAction = mixer.clipAction( clip );
+			const animationAction = mixer.clipAction( clip );
 			animationAction.setLoop( LoopOnce );
 			animationAction.clampWhenFinished = true;
 			animationAction.play();

+ 55 - 5
test/unit/src/animation/AnimationClip.tests.js

@@ -1,19 +1,55 @@
 /* global QUnit */
 
-// import { AnimationClip } from '../../../../src/animation/AnimationClip.js';
+import { AnimationClip } from '../../../../src/animation/AnimationClip.js';
 
 export default QUnit.module( 'Animation', () => {
 
 	QUnit.module( 'AnimationClip', () => {
 
 		// INSTANCING
-		QUnit.todo( 'Instancing', ( assert ) => {
+		QUnit.test( 'Instancing', ( assert ) => {
+
+			const clip = new AnimationClip( 'clip1', 1000, [ {} ] );
+			assert.ok( clip, 'AnimationClip can be instanciated' );
+
+		} );
+
+		// PROPERTIES
+		QUnit.test( 'name', ( assert ) => {
+
+			const clip = new AnimationClip( 'clip1', 1000, [ {} ] );
+			assert.strictEqual(
+				clip.name === 'clip1', true,
+				'AnimationClip can be named'
+			);
+
+		} );
+
+		QUnit.todo( 'tracks', ( assert ) => {
+
+			assert.ok( false, 'everything\'s gonna be alright' );
+
+		} );
+
+		QUnit.todo( 'duration', ( assert ) => {
+
+			assert.ok( false, 'everything\'s gonna be alright' );
+
+		} );
+
+		QUnit.todo( 'blendMode', ( assert ) => {
 
 			assert.ok( false, 'everything\'s gonna be alright' );
 
 		} );
 
-		// STATIC STUFF
+		QUnit.todo( 'uuid', ( assert ) => {
+
+			assert.ok( false, 'everything\'s gonna be alright' );
+
+		} );
+
+		// STATIC
 		QUnit.todo( 'parse', ( assert ) => {
 
 			assert.ok( false, 'everything\'s gonna be alright' );
@@ -22,6 +58,7 @@ export default QUnit.module( 'Animation', () => {
 
 		QUnit.todo( 'toJSON', ( assert ) => {
 
+			// static toJSON
 			assert.ok( false, 'everything\'s gonna be alright' );
 
 		} );
@@ -50,7 +87,7 @@ export default QUnit.module( 'Animation', () => {
 
 		} );
 
-		// PUBLIC STUFF
+		// PUBLIC
 		QUnit.todo( 'resetDuration', ( assert ) => {
 
 			assert.ok( false, 'everything\'s gonna be alright' );
@@ -63,14 +100,27 @@ export default QUnit.module( 'Animation', () => {
 
 		} );
 
+		QUnit.todo( 'validate', ( assert ) => {
+
+			assert.ok( false, 'everything\'s gonna be alright' );
+
+		} );
+
 		QUnit.todo( 'optimize', ( assert ) => {
 
 			assert.ok( false, 'everything\'s gonna be alright' );
 
 		} );
 
-		QUnit.todo( 'validate', ( assert ) => {
+		QUnit.todo( 'clone', ( assert ) => {
+
+			assert.ok( false, 'everything\'s gonna be alright' );
+
+		} );
+
+		QUnit.todo( 'toJSON', ( assert ) => {
 
+			// member method toJSON
 			assert.ok( false, 'everything\'s gonna be alright' );
 
 		} );

+ 28 - 3
test/unit/src/animation/AnimationMixer.tests.js

@@ -1,6 +1,8 @@
 /* global QUnit */
 
 import { AnimationMixer } from '../../../../src/animation/AnimationMixer.js';
+
+import { EventDispatcher } from '../../../../src/core/EventDispatcher.js';
 import { AnimationClip } from '../../../../src/animation/AnimationClip.js';
 import { VectorKeyframeTrack } from '../../../../src/animation/tracks/VectorKeyframeTrack.js';
 import { Object3D } from '../../../../src/core/Object3D.js';
@@ -25,9 +27,13 @@ export default QUnit.module( 'Animation', () => {
 	QUnit.module( 'AnimationMixer', () => {
 
 		// INHERITANCE
-		QUnit.todo( 'Extending', ( assert ) => {
+		QUnit.test( 'Extending', ( assert ) => {
 
-			assert.ok( false, 'everything\'s gonna be alright' );
+			const object = new AnimationMixer();
+			assert.strictEqual(
+				object instanceof EventDispatcher, true,
+				'AnimationMixer extends from EventDispatcher'
+			);
 
 		} );
 
@@ -38,7 +44,20 @@ export default QUnit.module( 'Animation', () => {
 
 		} );
 
-		// PUBLIC STUFF
+		// PROPERTIES
+		QUnit.todo( 'time', ( assert ) => {
+
+			assert.ok( false, 'everything\'s gonna be alright' );
+
+		} );
+
+		QUnit.todo( 'timeScale', ( assert ) => {
+
+			assert.ok( false, 'everything\'s gonna be alright' );
+
+		} );
+
+		// PUBLIC
 		QUnit.todo( 'clipAction', ( assert ) => {
 
 			assert.ok( false, 'everything\'s gonna be alright' );
@@ -89,6 +108,12 @@ export default QUnit.module( 'Animation', () => {
 
 		} );
 
+		QUnit.todo( 'setTime', ( assert ) => {
+
+			assert.ok( false, 'everything\'s gonna be alright' );
+
+		} );
+
 		QUnit.test( 'getRoot', ( assert ) => {
 
 			const obj = new Object3D();

+ 33 - 11
test/unit/src/animation/AnimationObjectGroup.tests.js

@@ -1,6 +1,7 @@
 /* global QUnit */
 
 import { AnimationObjectGroup } from '../../../../src/animation/AnimationObjectGroup.js';
+
 import { Object3D } from '../../../../src/core/Object3D.js';
 import { PropertyBinding } from '../../../../src/animation/PropertyBinding.js';
 
@@ -8,7 +9,7 @@ export default QUnit.module( 'Animation', () => {
 
 	QUnit.module( 'AnimationObjectGroup', () => {
 
-		var ObjectA = new Object3D(),
+		const ObjectA = new Object3D(),
 			ObjectB = new Object3D(),
 			ObjectC = new Object3D(),
 
@@ -21,19 +22,40 @@ export default QUnit.module( 'Animation', () => {
 			ParsedPathC = PropertyBinding.parseTrackName( PathC );
 
 		// INSTANCING
-		QUnit.todo( 'Instancing', ( assert ) => {
+		QUnit.test( 'Instancing', ( assert ) => {
+
+			const groupA = new AnimationObjectGroup();
+			assert.ok(
+				groupA instanceof AnimationObjectGroup,
+				'AnimationObjectGroup can be instanciated'
+			);
+
+		} );
+
+		// PROPERTIES
+		QUnit.todo( 'uuid', ( assert ) => {
 
 			assert.ok( false, 'everything\'s gonna be alright' );
 
 		} );
 
-		// PUBLIC STUFF
-		QUnit.todo( 'isAnimationObjectGroup', ( assert ) => {
+		QUnit.todo( 'stats', ( assert ) => {
 
 			assert.ok( false, 'everything\'s gonna be alright' );
 
 		} );
 
+		// PUBLIC
+		QUnit.test( 'isAnimationObjectGroup', ( assert ) => {
+
+			const object = new AnimationObjectGroup();
+			assert.ok(
+				object.isAnimationObjectGroup,
+				'AnimationObjectGroup.isAnimationObjectGroup should be true'
+			);
+
+		} );
+
 		QUnit.todo( 'add', ( assert ) => {
 
 			assert.ok( false, 'everything\'s gonna be alright' );
@@ -81,16 +103,16 @@ export default QUnit.module( 'Animation', () => {
 
 			// initial state
 
-			var groupA = new AnimationObjectGroup();
+			const groupA = new AnimationObjectGroup();
 			assert.ok( groupA instanceof AnimationObjectGroup, 'constructor (w/o args)' );
 
-			var bindingsAA = groupA.subscribe_( PathA, ParsedPathA );
+			const bindingsAA = groupA.subscribe_( PathA, ParsedPathA );
 			expect( 0, groupA, bindingsAA, PathA, 0, [] );
 
-			var groupB = new AnimationObjectGroup( ObjectA, ObjectB );
+			const groupB = new AnimationObjectGroup( ObjectA, ObjectB );
 			assert.ok( groupB instanceof AnimationObjectGroup, 'constructor (with args)' );
 
-			var bindingsBB = groupB.subscribe_( PathB, ParsedPathB );
+			const bindingsBB = groupB.subscribe_( PathB, ParsedPathB );
 			expect( 1, groupB, bindingsBB, PathB, 0, [ ObjectA, ObjectB ] );
 
 			// add
@@ -113,18 +135,18 @@ export default QUnit.module( 'Animation', () => {
 
 			groupA.add( ObjectC );
 			expect( 6, groupA, bindingsAA, PathA, 1, [ ObjectB, ObjectC ] );
-			var bindingsAC = groupA.subscribe_( PathC, ParsedPathC );
+			const bindingsAC = groupA.subscribe_( PathC, ParsedPathC );
 			expect( 7, groupA, bindingsAC, PathC, 1, [ ObjectB, ObjectC ] );
 
 			// re-add after subscribe
 
-			var bindingsBC = groupB.subscribe_( PathC, ParsedPathC );
+			const bindingsBC = groupB.subscribe_( PathC, ParsedPathC );
 			groupB.add( ObjectA, ObjectB );
 			expect( 8, groupB, bindingsBB, PathB, 1, [ ObjectA, ObjectB ] );
 
 			// unsubscribe
 
-			var copyOfBindingsBC = bindingsBC.slice();
+			const copyOfBindingsBC = bindingsBC.slice();
 			groupB.unsubscribe_( PathC );
 			groupB.add( ObjectC );
 			assert.deepEqual( bindingsBC, copyOfBindingsBC, 'no more update after unsubscribe' );

+ 13 - 1
test/unit/src/animation/AnimationUtils.tests.js

@@ -6,7 +6,7 @@ export default QUnit.module( 'Animation', () => {
 
 	QUnit.module( 'AnimationUtils', () => {
 
-		// PUBLIC STUFF
+		// PUBLIC
 		QUnit.todo( 'arraySlice', ( assert ) => {
 
 			assert.ok( false, 'everything\'s gonna be alright' );
@@ -43,6 +43,18 @@ export default QUnit.module( 'Animation', () => {
 
 		} );
 
+		QUnit.todo( 'subclip', ( assert ) => {
+
+			assert.ok( false, 'everything\'s gonna be alright' );
+
+		} );
+
+		QUnit.todo( 'makeClipAdditive', ( assert ) => {
+
+			assert.ok( false, 'everything\'s gonna be alright' );
+
+		} );
+
 	} );
 
 } );

+ 34 - 6
test/unit/src/animation/KeyframeTrack.tests.js

@@ -1,6 +1,7 @@
 /* global QUnit */
 
 import { NumberKeyframeTrack } from '../../../../src/animation/tracks/NumberKeyframeTrack.js';
+
 import { CONSOLE_LEVEL } from '../../utils/console-wrapper.js';
 
 export default QUnit.module( 'Animation', () => {
@@ -14,14 +15,26 @@ export default QUnit.module( 'Animation', () => {
 
 		} );
 
-		// STATIC STUFF
-		QUnit.todo( 'toJSON', ( assert ) => {
+		// PROPERTIES
+		QUnit.todo( 'name', ( assert ) => {
+
+			assert.ok( false, 'everything\'s gonna be alright' );
+
+		} );
+
+		QUnit.todo( 'times', ( assert ) => {
+
+			assert.ok( false, 'everything\'s gonna be alright' );
+
+		} );
+
+		QUnit.todo( 'values', ( assert ) => {
 
 			assert.ok( false, 'everything\'s gonna be alright' );
 
 		} );
 
-		// PUBLIC STUFF
+		// PROPERTIES - PROTOTYPE
 		QUnit.todo( 'TimeBufferType', ( assert ) => {
 
 			assert.ok( false, 'everything\'s gonna be alright' );
@@ -40,6 +53,15 @@ export default QUnit.module( 'Animation', () => {
 
 		} );
 
+		// STATIC
+		QUnit.todo( 'toJSON', ( assert ) => {
+
+			// static method toJSON
+			assert.ok( false, 'everything\'s gonna be alright' );
+
+		} );
+
+		// PUBLIC
 		QUnit.todo( 'InterpolantFactoryMethodDiscrete', ( assert ) => {
 
 			assert.ok( false, 'everything\'s gonna be alright' );
@@ -96,8 +118,8 @@ export default QUnit.module( 'Animation', () => {
 
 		QUnit.test( 'validate', ( assert ) => {
 
-			var validTrack = new NumberKeyframeTrack( '.material.opacity', [ 0, 1 ], [ 0, 0.5 ] );
-			var invalidTrack = new NumberKeyframeTrack( '.material.opacity', [ 0, 1 ], [ 0, NaN ] );
+			const validTrack = new NumberKeyframeTrack( '.material.opacity', [ 0, 1 ], [ 0, 0.5 ] );
+			const invalidTrack = new NumberKeyframeTrack( '.material.opacity', [ 0, 1 ], [ 0, NaN ] );
 
 			assert.ok( validTrack.validate() );
 
@@ -109,7 +131,7 @@ export default QUnit.module( 'Animation', () => {
 
 		QUnit.test( 'optimize', ( assert ) => {
 
-			var track = new NumberKeyframeTrack( '.material.opacity', [ 0, 1, 2, 3, 4 ], [ 0, 0, 0, 0, 1 ] );
+			const track = new NumberKeyframeTrack( '.material.opacity', [ 0, 1, 2, 3, 4 ], [ 0, 0, 0, 0, 1 ] );
 
 			assert.equal( track.values.length, 5 );
 
@@ -120,6 +142,12 @@ export default QUnit.module( 'Animation', () => {
 
 		} );
 
+		QUnit.todo( 'clone', ( assert ) => {
+
+			assert.ok( false, 'everything\'s gonna be alright' );
+
+		} );
+
 	} );
 
 } );

+ 10 - 9
test/unit/src/animation/PropertyBinding.tests.js

@@ -1,6 +1,7 @@
 /* global QUnit */
 
 import { PropertyBinding } from '../../../../src/animation/PropertyBinding.js';
+
 import { BoxGeometry } from '../../../../src/geometries/BoxGeometry.js';
 import { Mesh } from '../../../../src/objects/Mesh.js';
 import { MeshBasicMaterial } from '../../../../src/materials/MeshBasicMaterial.js';
@@ -16,7 +17,7 @@ export default QUnit.module( 'Animation', () => {
 
 		} );
 
-		// STATIC STUFF
+		// STATIC
 		QUnit.todo( 'Composite', ( assert ) => {
 
 			assert.ok( false, 'everything\'s gonna be alright' );
@@ -65,7 +66,7 @@ export default QUnit.module( 'Animation', () => {
 
 		QUnit.test( 'parseTrackName', ( assert ) => {
 
-			var paths = [
+			const paths = [
 
 				[
 					'.property',
@@ -321,22 +322,22 @@ export default QUnit.module( 'Animation', () => {
 
 		QUnit.test( 'setValue', ( assert ) => {
 
-			var paths = [
+			const paths = [
 				'.material.opacity',
 				'.material[opacity]'
 			];
 
 			paths.forEach( function ( path ) {
 
-				var originalValue = 0;
-				var expectedValue = 1;
+				const originalValue = 0;
+				const expectedValue = 1;
 
-				var geometry = new BoxGeometry();
-				var material = new MeshBasicMaterial();
+				const geometry = new BoxGeometry();
+				const material = new MeshBasicMaterial();
 				material.opacity = originalValue;
-				var mesh = new Mesh( geometry, material );
+				const mesh = new Mesh( geometry, material );
 
-				var binding = new PropertyBinding( mesh, path, null );
+				const binding = new PropertyBinding( mesh, path, null );
 				binding.bind();
 
 				assert.equal(

+ 50 - 1
test/unit/src/animation/PropertyMixer.tests.js

@@ -13,13 +13,62 @@ export default QUnit.module( 'Animation', () => {
 
 		} );
 
-		// PUBLIC STUFF
+		// PROPERTIES
+		QUnit.todo( 'binding', ( assert ) => {
+
+			assert.ok( false, 'everything\'s gonna be alright' );
+
+		} );
+
+		QUnit.todo( 'valueSize', ( assert ) => {
+
+			assert.ok( false, 'everything\'s gonna be alright' );
+
+		} );
+
+		QUnit.todo( 'buffer', ( assert ) => {
+
+			assert.ok( false, 'everything\'s gonna be alright' );
+
+		} );
+
+		QUnit.todo( 'cumulativeWeight', ( assert ) => {
+
+			assert.ok( false, 'everything\'s gonna be alright' );
+
+		} );
+
+		QUnit.todo( 'cumulativeWeightAdditive', ( assert ) => {
+
+			assert.ok( false, 'everything\'s gonna be alright' );
+
+		} );
+
+		QUnit.todo( 'useCount', ( assert ) => {
+
+			assert.ok( false, 'everything\'s gonna be alright' );
+
+		} );
+
+		QUnit.todo( 'referenceCount', ( assert ) => {
+
+			assert.ok( false, 'everything\'s gonna be alright' );
+
+		} );
+
+		// PUBLIC
 		QUnit.todo( 'accumulate', ( assert ) => {
 
 			assert.ok( false, 'everything\'s gonna be alright' );
 
 		} );
 
+		QUnit.todo( 'accumulateAdditive', ( assert ) => {
+
+			assert.ok( false, 'everything\'s gonna be alright' );
+
+		} );
+
 		QUnit.todo( 'apply', ( assert ) => {
 
 			assert.ok( false, 'everything\'s gonna be alright' );

+ 16 - 2
test/unit/src/animation/tracks/BooleanKeyframeTrack.tests.js

@@ -1,6 +1,8 @@
 /* global QUnit */
 
-// import { BooleanKeyframeTrack } from '../../../../../src/animation/tracks/BooleanKeyframeTrack.js';
+import { BooleanKeyframeTrack } from '../../../../../src/animation/tracks/BooleanKeyframeTrack.js';
+
+import { KeyframeTrack } from '../../../../../src/animation/KeyframeTrack.js';
 
 export default QUnit.module( 'Animation', () => {
 
@@ -8,7 +10,19 @@ export default QUnit.module( 'Animation', () => {
 
 		QUnit.module( 'BooleanKeyframeTrack', () => {
 
-			QUnit.todo( 'write me !', ( assert ) => {
+			// INHERITANCE
+			QUnit.test( 'Extending', ( assert ) => {
+
+				const object = new BooleanKeyframeTrack( '.visible', [ 0, 1 ], [ true, false ] );
+				assert.strictEqual(
+					object instanceof KeyframeTrack, true,
+					'BooleanKeyframeTrack extends from KeyframeTrack'
+				);
+
+			} );
+
+			// INSTANCING
+			QUnit.todo( 'Instancing', ( assert ) => {
 
 				assert.ok( false, 'everything\'s gonna be alright' );
 

+ 16 - 2
test/unit/src/animation/tracks/ColorKeyframeTrack.tests.js

@@ -1,6 +1,8 @@
 /* global QUnit */
 
-// import { ColorKeyframeTrack } from '../../../../../src/animation/tracks/ColorKeyframeTrack.js';
+import { ColorKeyframeTrack } from '../../../../../src/animation/tracks/ColorKeyframeTrack.js';
+
+import { KeyframeTrack } from '../../../../../src/animation/KeyframeTrack.js';
 
 export default QUnit.module( 'Animation', () => {
 
@@ -8,7 +10,19 @@ export default QUnit.module( 'Animation', () => {
 
 		QUnit.module( 'ColorKeyframeTrack', () => {
 
-			QUnit.todo( 'write me !', ( assert ) => {
+			// INHERITANCE
+			QUnit.test( 'Extending', ( assert ) => {
+
+				const object = new ColorKeyframeTrack( '.material.diffuse', [ 0, 1 ], [ 0, 0.5, 1.0 ] );
+				assert.strictEqual(
+					object instanceof KeyframeTrack, true,
+					'ColorKeyframeTrack extends from KeyframeTrack'
+				);
+
+			} );
+
+			// INSTANCING
+			QUnit.todo( 'Instancing', ( assert ) => {
 
 				assert.ok( false, 'everything\'s gonna be alright' );
 

+ 16 - 2
test/unit/src/animation/tracks/NumberKeyframeTrack.tests.js

@@ -1,6 +1,8 @@
 /* global QUnit */
 
-// import { NumberKeyframeTrack } from '../../../../../src/animation/tracks/NumberKeyframeTrack.js';
+import { NumberKeyframeTrack } from '../../../../../src/animation/tracks/NumberKeyframeTrack.js';
+
+import { KeyframeTrack } from '../../../../../src/animation/KeyframeTrack.js';
 
 export default QUnit.module( 'Animation', () => {
 
@@ -8,7 +10,19 @@ export default QUnit.module( 'Animation', () => {
 
 		QUnit.module( 'NumberKeyframeTrack', () => {
 
-			QUnit.todo( 'write me !', ( assert ) => {
+			// INHERITANCE
+			QUnit.test( 'Extending', ( assert ) => {
+
+				const object = new NumberKeyframeTrack( '.material.opacity', [ 0, 1 ], [ 0, 0.5 ] );
+				assert.strictEqual(
+					object instanceof KeyframeTrack, true,
+					'NumberKeyframeTrack extends from KeyframeTrack'
+				);
+
+			} );
+
+			// INSTANCING
+			QUnit.todo( 'Instancing', ( assert ) => {
 
 				assert.ok( false, 'everything\'s gonna be alright' );
 

+ 16 - 2
test/unit/src/animation/tracks/QuaternionKeyframeTrack.tests.js

@@ -1,6 +1,8 @@
 /* global QUnit */
 
-// import { QuaternionKeyframeTrack } from '../../../../../src/animation/tracks/QuaternionKeyframeTrack.js';
+import { QuaternionKeyframeTrack } from '../../../../../src/animation/tracks/QuaternionKeyframeTrack.js';
+
+import { KeyframeTrack } from '../../../../../src/animation/KeyframeTrack.js';
 
 export default QUnit.module( 'Animation', () => {
 
@@ -8,7 +10,19 @@ export default QUnit.module( 'Animation', () => {
 
 		QUnit.module( 'QuaternionKeyframeTrack', () => {
 
-			QUnit.todo( 'write me !', ( assert ) => {
+			// INHERITANCE
+			QUnit.test( 'Extending', ( assert ) => {
+
+				const object = new QuaternionKeyframeTrack( '.rotation', [ 0 ], [ 0.5, 0.5, 0.5, 1 ] );
+				assert.strictEqual(
+					object instanceof KeyframeTrack, true,
+					'QuaternionKeyframeTrack extends from KeyframeTrack'
+				);
+
+			} );
+
+			// INSTANCING
+			QUnit.todo( 'Instancing', ( assert ) => {
 
 				assert.ok( false, 'everything\'s gonna be alright' );
 

+ 16 - 2
test/unit/src/animation/tracks/StringKeyframeTrack.tests.js

@@ -1,6 +1,8 @@
 /* global QUnit */
 
-// import { StringKeyframeTrack } from '../../../../../src/animation/tracks/StringKeyframeTrack.js';
+import { StringKeyframeTrack } from '../../../../../src/animation/tracks/StringKeyframeTrack.js';
+
+import { KeyframeTrack } from '../../../../../src/animation/KeyframeTrack.js';
 
 export default QUnit.module( 'Animation', () => {
 
@@ -8,7 +10,19 @@ export default QUnit.module( 'Animation', () => {
 
 		QUnit.module( 'StringKeyframeTrack', () => {
 
-			QUnit.todo( 'write me !', ( assert ) => {
+			// INHERITANCE
+			QUnit.test( 'Extending', ( assert ) => {
+
+				const object = new StringKeyframeTrack( '.name', [ 0, 1 ], [ 'foo', 'bar' ] );
+				assert.strictEqual(
+					object instanceof KeyframeTrack, true,
+					'StringKeyframeTrack extends from KeyframeTrack'
+				);
+
+			} );
+
+			// INSTANCING
+			QUnit.todo( 'Instancing', ( assert ) => {
 
 				assert.ok( false, 'everything\'s gonna be alright' );
 

+ 16 - 2
test/unit/src/animation/tracks/VectorKeyframeTrack.tests.js

@@ -1,6 +1,8 @@
 /* global QUnit */
 
-//import { VectorKeyframeTrack } from '../../../../../src/animation/tracks/VectorKeyframeTrack.js';
+import { VectorKeyframeTrack } from '../../../../../src/animation/tracks/VectorKeyframeTrack.js';
+
+import { KeyframeTrack } from '../../../../../src/animation/KeyframeTrack.js';
 
 export default QUnit.module( 'Animation', () => {
 
@@ -8,7 +10,19 @@ export default QUnit.module( 'Animation', () => {
 
 		QUnit.module( 'VectorKeyframeTrack', () => {
 
-			QUnit.todo( 'write me !', ( assert ) => {
+			// INHERITANCE
+			QUnit.test( 'Extending', ( assert ) => {
+
+				const object = new VectorKeyframeTrack( '.force', [ 0 ], [ 0.5, 0.5, 0.5 ] );
+				assert.strictEqual(
+					object instanceof KeyframeTrack, true,
+					'VectorKeyframeTrack extends from KeyframeTrack'
+				);
+
+			} );
+
+			// INSTANCING
+			QUnit.todo( 'Instancing', ( assert ) => {
 
 				assert.ok( false, 'everything\'s gonna be alright' );