@@ -66,6 +66,112 @@ describe("Utility functions", () => {
6666 expect ( isNumeric ( "0xAF" ) ) . to . be . false ;
6767 } ) ;
6868 } ) ;
69+
70+ describe ( "tween()" , function ( ) {
71+ const { tween, wait} = utils ;
72+ const duration = 600 ;
73+ this . timeout ( duration * 2 ) ;
74+ this . slow ( duration * 4 ) ;
75+
76+ it ( "interpolates property values over time" , async ( ) => {
77+ const target = { prop : 0 } ;
78+ const tweenValue = tween ( target , "prop" , 100 , { duration} ) ;
79+ await wait ( duration / 3 ) . then ( ( ) => expect ( target . prop ) . to . be . within ( 10 , 50 ) ) ;
80+ await wait ( duration / 2 ) . then ( ( ) => expect ( target . prop ) . to . be . within ( 50 , 100 ) ) ;
81+ await tweenValue . then ( ( ) => expect ( target . prop ) . to . equal ( 100 ) ) ;
82+ } ) ;
83+
84+ it ( "begins tweening from the existing value" , async ( ) => {
85+ const target = { prop : 90 } ;
86+ const tweenValue = tween ( target , "prop" , 100 , { duration} ) ;
87+ await wait ( duration / 3 ) . then ( ( ) => expect ( target . prop ) . to . be . within ( 90 , 100 ) ) ;
88+ await tweenValue . then ( ( ) => expect ( target . prop ) . to . equal ( 100 ) ) ;
89+ } ) ;
90+
91+ it ( "invokes callback functions for each frame" , async ( ) => {
92+ let callCount = 0 ;
93+ const fps = 5 ;
94+ const target = { prop : 0 } ;
95+ const previous = { value : - 1 , progress : - 1 } ;
96+ const callback = ( value , progress ) => {
97+ expect ( value ) . to . be . above ( previous . value ) ;
98+ expect ( progress ) . to . be . above ( previous . progress ) . and . within ( 0 , 1 ) ;
99+ previous . value = value ;
100+ previous . progress = progress ;
101+ ++ callCount ;
102+ } ;
103+ await tween ( target , "prop" , 10 , { duration, callback, fps} ) ;
104+ expect ( callCount ) . to . be . at . least ( duration / 60 / fps ) ;
105+ expect ( previous . progress ) . to . equal ( 1 ) ;
106+ } ) ;
107+
108+ it ( "supports custom easing curves" , async ( ) => {
109+ const target = { foo : 0 , bar : 0 } ;
110+ const tweenA = tween ( target , "foo" , 100 , { duration, curve : [ [ 0 , 0 ] , [ 1 , 0 ] , [ 1 , 0 ] , [ 1 , 1 ] ] } ) ;
111+ const tweenB = tween ( target , "bar" , 100 , { duration, curve : [ [ 0 , 0 ] , [ 0 , 1 ] , [ 0 , 1 ] , [ 1 , 1 ] ] } ) ;
112+ await wait ( duration / 4 ) ;
113+ expect ( target . foo ) . to . be . below ( 5 ) ;
114+ expect ( target . bar ) . to . be . above ( 35 ) ;
115+ await wait ( duration / 2 ) ;
116+ expect ( target . foo ) . to . be . below ( 50 ) ;
117+ expect ( target . bar ) . to . be . above ( 85 ) ;
118+ await tweenA . then ( ( ) => expect ( target . foo ) . to . equal ( 100 ) ) ;
119+ await tweenB . then ( ( ) => expect ( target . bar ) . to . equal ( 100 ) ) ;
120+ } ) ;
121+
122+ it ( "supports early cancellation of playback" , async ( ) => {
123+ const valuesWhenStopped = { A : 0 , B : 0 } ;
124+ const target = { foo : 0 , bar : 0 } ;
125+ const tweenA = tween ( target , "foo" , 10 , { duration} ) ;
126+ const tweenB = tween ( target , "bar" , 10 , { duration} ) ;
127+ await wait ( duration / 4 ) . then ( ( ) => expect ( target . foo ) . to . be . above ( 0 ) )
128+ await wait ( duration / 2 ) . then ( ( ) => tweenA . stop ( ) ) ;
129+ valuesWhenStopped . A = target . foo ;
130+ valuesWhenStopped . B = target . bar ;
131+ expect ( valuesWhenStopped . A ) . to . be . above ( 0 ) . and . below ( 10 ) ;
132+ expect ( valuesWhenStopped . B ) . to . be . above ( 0 ) . and . below ( 10 ) ;
133+ await wait ( duration / 1.5 ) ;
134+ expect ( target . foo ) . to . equal ( valuesWhenStopped . A ) ;
135+ expect ( target . bar ) . to . be . above ( valuesWhenStopped . B ) . and . to . equal ( 10 ) ;
136+ } ) ;
137+
138+ it ( "defines presets for common easing functions" , ( ) => {
139+ expect ( tween . LINEAR ) . to . be . an ( "array" ) ;
140+ expect ( tween . EASE ) . to . be . an ( "array" ) ;
141+ expect ( tween . EASE_IN ) . to . be . an ( "array" ) ;
142+ expect ( tween . EASE_IN_OUT ) . to . be . an ( "array" ) ;
143+ expect ( tween . EASE_OUT ) . to . be . an ( "array" ) ;
144+ } ) ;
145+
146+ it ( "lets durations be specified" , async ( ) => {
147+ const target = { foo : 0 , bar : 0 } ;
148+ const result = [ ] ;
149+ const tweenA = tween ( target , "foo" , 5 , { duration : 500 } ) . then ( ( ) => result . push ( "A" ) ) ;
150+ const tweenB = tween ( target , "bar" , 5 , { duration : 250 } ) . then ( ( ) => result . push ( "B" ) ) ;
151+ await Promise . all ( [ tweenA , tweenB ] ) ;
152+ expect ( result ) . to . eql ( [ "B" , "A" ] ) ;
153+ } ) ;
154+
155+ it ( "lets frame rates be specified" , async ( ) => {
156+ const counts = { A : 0 , B : 0 } ;
157+ const target = { foo : 0 , bar : 0 } ;
158+ const tweenA = tween ( target , "foo" , 5 , { duration, fps : 50 , callback : ( ) => ++ counts . A } ) ;
159+ const tweenB = tween ( target , "bar" , 5 , { duration, fps : 25 , callback : ( ) => ++ counts . B } ) ;
160+ await Promise . all ( [ tweenA , tweenB ] ) ;
161+ expect ( counts . A ) . to . be . above ( counts . B ) ;
162+ expect ( target . foo ) . to . equal ( target . bar ) ;
163+ } ) ;
164+
165+ it ( "lets interpolated values be overridden by a filter" , async ( ) => {
166+ const target = { prop : 0 } ;
167+ const filter = ( value , progress ) => {
168+ expect ( progress ) . to . be . within ( 0 , 1 ) ;
169+ return `Size: ${ value } cm × ${ value / 2 } cm` ;
170+ } ;
171+ await tween ( target , "prop" , 30 , { duration, filter} ) ;
172+ expect ( target . prop ) . to . equal ( "Size: 30cm × 15cm" ) ;
173+ } ) ;
174+ } ) ;
69175 } ) ;
70176
71177 describe ( "Regular expressions" , ( ) => {
0 commit comments