1suite('matrix interpolation', function() {
2  function compareMatrices(actual, expected, expectedLength) {
3    var actualElements = actual.slice(
4        actual.indexOf('(') + 1, actual.lastIndexOf(')')).split(',');
5    assert.equal(actualElements.length, expectedLength);
6    for (var i = 0; i < expectedLength; i++)
7      assert.closeTo(Number(actualElements[i]), expected[i], 0.01);
8  }
9
10  function compareInterpolatedTransforms(actual, expected, timeFraction) {
11    var actualInterp = webAnimations1.propertyInterpolation(
12        'transform',
13        actual[0],
14        actual[1]);
15    var expectedInterp = webAnimations1.propertyInterpolation(
16        'transform',
17        expected[0],
18        expected[1]);
19    var evaluatedActualInterp = actualInterp(timeFraction);
20    var evaluatedExpectedInterp = expectedInterp(timeFraction);
21    var actualElements = evaluatedActualInterp.slice(
22        evaluatedActualInterp.indexOf('(') + 1,
23        evaluatedActualInterp.lastIndexOf(')')
24        ).split(',');
25    var expectedElements = evaluatedExpectedInterp.slice(
26        evaluatedExpectedInterp.indexOf('(') + 1,
27        evaluatedExpectedInterp.lastIndexOf(')')
28        ).split(',');
29    assert.equal(actualElements.length, expectedElements.length);
30    for (var i = 0; i < expectedElements.length; i++)
31      assert.closeTo(Number(actualElements[i]), Number(expectedElements[i]), 0.01);
32  }
33
34  test('transform interpolations with matrices only', function() {
35    var interpolatedMatrix = webAnimations1.propertyInterpolation(
36        'transform',
37        'matrix(1, 0, 0, 1, 0, 0)',
38        'matrix(1, -0.2, 0, 1, 0, 0)');
39    var evaluatedInterp = interpolatedMatrix(0.5);
40    compareMatrices(evaluatedInterp, [1, -0.1, 0, 1, 0, 0], 6);
41
42    interpolatedMatrix = webAnimations1.propertyInterpolation(
43        'transform',
44        'matrix(1, 0, 0, 1, 0, 0)',
45        'matrix3d(1, 1, 0, 0, -2, 1, 0, 0, 0, 0, 1, 0, 10, 10, 0, 1)');
46    evaluatedInterp = interpolatedMatrix(0.5);
47    compareMatrices(evaluatedInterp, [1.12, 0.46, -0.84, 1.34, 5, 5], 6);
48
49    interpolatedMatrix = webAnimations1.propertyInterpolation(
50        'transform',
51        'matrix(1, 0, 0, 1, 0, 0)',
52        'matrix3d(1, 1, 3, 0, -2, 1, 0, 0, 0, 0, 1, 0, 10, 10, 0, 1)');
53    evaluatedInterp = interpolatedMatrix(0.5);
54    // FIXME: Values at 8, 9, 10 are different from Blink and FireFox, which give 0.31, 0.04, 1.01.
55    // Result looks the same.
56    compareMatrices(
57        evaluatedInterp,
58        [1.73, 0.67, 1.10, 0, -0.85, 1.34, 0.29, 0, -0.35, -0.22, 0.58, 0, 5, 5, 0, 1],
59        16);
60
61    interpolatedMatrix = webAnimations1.propertyInterpolation(
62        'transform',
63        'matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1)',
64        'matrix3d(1, 2, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 10, 10, 1)');
65    evaluatedInterp = interpolatedMatrix(0.5);
66    compareMatrices(
67        evaluatedInterp,
68        [1.38, 0.85, 0, 0, 0.24, 1.00, 0, 0, 0, 0, 1, 0, 0, 5, 5, 1],
69        16);
70
71    interpolatedMatrix = webAnimations1.propertyInterpolation(
72        'transform',
73        'matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1)',
74        'matrix3d(1, 1, 0, 0, -2, 1, 0, 0, 0, 0, 1, 0, 10, 10, 0, 1)');
75    evaluatedInterp = interpolatedMatrix(0.5);
76    compareMatrices(evaluatedInterp, [1.12, 0.46, -0.84, 1.34, 5, 5], 6);
77
78    // Test matrices with [3][3] != 1
79    interp = webAnimations1.propertyInterpolation(
80        'transform',
81        'matrix(1, 0, 0, 1, 0, 0)',
82        'matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 2)');
83    evaluatedInterp = interp(0.4);
84    compareMatrices(
85        evaluatedInterp,
86        [1, 0, 0, 1, 0, 0],
87        6);
88    evaluatedInterp = interp(0.6);
89    compareMatrices(
90        evaluatedInterp,
91        [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 2],
92        16);
93  });
94
95  test('transform interpolations with matrices and other functions', function() {
96    var interp = webAnimations1.propertyInterpolation(
97        'transform',
98        'translate(100px) matrix(1, 0, 0, 1, 0, 0)',
99        'translate(10px) matrix(1, -0.2, 0, 1, 0, 0)');
100    var evaluatedInterp = interp(0.5);
101    var functions = evaluatedInterp.split(' ');
102    assert.equal(functions.length, 2);
103    assert.equal(functions[0], 'translate(55px,0px)');
104    compareMatrices(functions[1], [1, -0.1, 0, 1, 0, 0], 6);
105
106    interp = webAnimations1.propertyInterpolation(
107        'transform',
108        'translate(100px) matrix(1, 0, 0, 1, 0, 0) rotate(10deg)',
109        'translate(10px) matrix(1, -0.2, 0, 1, 0, 0) rotate(100deg)');
110    evaluatedInterp = interp(0.5);
111    functions = evaluatedInterp.split(' ');
112    assert.equal(functions.length, 3);
113    assert.equal(functions[0], 'translate(55px,0px)');
114    compareMatrices(functions[1], [1, -0.1, 0, 1, 0, 0], 6);
115    assert.equal(functions[2], 'rotate(55deg)');
116
117    interp = webAnimations1.propertyInterpolation(
118        'transform',
119        'translate(100px) matrix(1, 0, 0, 1, 0, 0) rotate(10deg)',
120        'translate(10px) matrix3d(1, 2, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 10, 10, 1) rotate(100deg)');
121    evaluatedInterp = interp(0.5);
122    functions = evaluatedInterp.split(' ');
123    assert.equal(functions.length, 3);
124    assert.equal(functions[0], 'translate(55px,0px)');
125    compareMatrices(
126        functions[1],
127        [1.38, 0.85, 0, 0, 0.24, 1.00, 0, 0, 0, 0, 1, 0, 0, 5, 5, 1],
128        16);
129    assert.equal(functions[2], 'rotate(55deg)');
130
131    // Contains matrices and requires matrix decomposition.
132    interp = webAnimations1.propertyInterpolation(
133        'transform',
134        'matrix(1, 0, 0, 1, 0, 0) translate(100px)',
135        'translate(10px) matrix(1, -0.2, 0, 1, 0, 0)');
136    evaluatedInterp = interp(0.5);
137    compareMatrices(evaluatedInterp, [1, -0.1, 0, 1, 55, 0], 6);
138
139    // Test matrices with [3][3] != 1
140    interp = webAnimations1.propertyInterpolation(
141        'transform',
142        'translate(100px) matrix(1, 0, 0, 1, 0, 0) rotate(10deg)',
143        'translate(10px) matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 2) rotate(100deg)');
144    evaluatedInterp = interp(0.4);
145    functions = evaluatedInterp.split(' ');
146    assert.equal(functions.length, 3);
147    assert.equal(functions[0], 'translate(64px,0px)');
148    compareMatrices(
149        functions[1],
150        [1, 0, 0, 1, 0, 0],
151        6);
152    assert.equal(functions[2], 'rotate(46deg)');
153    evaluatedInterp = interp(0.6);
154    functions = evaluatedInterp.split(' ');
155    assert.equal(functions.length, 3);
156    assert.equal(functions[0], 'translate(46px,0px)');
157    compareMatrices(
158        functions[1],
159        [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 2],
160        16);
161    assert.equal(functions[2], 'rotate(64deg)');
162
163    interp = webAnimations1.propertyInterpolation(
164        'transform',
165        'translate(10px) matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 2) rotate(100deg)',
166        'translate(100px) matrix(1, 0, 0, 1, 0, 0) rotate(10deg)');
167    evaluatedInterp = interp(0.4);
168    functions = evaluatedInterp.split(' ');
169    assert.equal(functions.length, 3);
170    assert.equal(functions[0], 'translate(46px,0px)');
171    compareMatrices(
172        functions[1],
173        [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 2],
174        16);
175    assert.equal(functions[2], 'rotate(64deg)');
176    evaluatedInterp = interp(0.6);
177    functions = evaluatedInterp.split(' ');
178    assert.equal(functions.length, 3);
179    assert.equal(functions[0], 'translate(64px,0px)');
180    compareMatrices(
181        functions[1],
182        [1, 0, 0, 1, 0, 0],
183        6);
184    assert.equal(functions[2], 'rotate(46deg)');
185  });
186
187  test('transform interpolations that require matrix decomposition', function() {
188    var interp = webAnimations1.propertyInterpolation(
189        'transform',
190        'translate(10px)',
191        'scale(2)');
192    var evaluatedInterp = interp(0.4);
193    compareMatrices(evaluatedInterp, [1.4, 0, 0, 1.4, 6, 0], 6);
194
195    interp = webAnimations1.propertyInterpolation(
196        'transform',
197        'rotateX(10deg)',
198        'rotateY(20deg)');
199    evaluatedInterp = interp(0.4);
200    compareMatrices(
201        evaluatedInterp,
202        [0.99, 0.01, -0.14, 0, 0.01, 1.00, 0.10, 0, 0.14, -0.10, 0.98, 0, 0, 0, 0, 1],
203        16);
204
205    interp = webAnimations1.propertyInterpolation(
206        'transform',
207        'rotate(0rad) translate(0px)',
208        'translate(800px) rotate(9rad)');
209    evaluatedInterp = interp(0.4);
210    compareMatrices(evaluatedInterp, [0.47, 0.89, -0.89, 0.47, 320, 0], 6);
211
212    interp = webAnimations1.propertyInterpolation(
213        'transform',
214        'rotateX(10deg)',
215        'translate(10px) rotateX(200deg)');
216    evaluatedInterp = interp(0.4);
217    compareMatrices(
218        evaluatedInterp,
219        [1, 0, 0, 0, 0, 0.53, -0.85, 0, 0, 0.85, 0.53, 0, 4, 0, 0, 1],
220        16);
221
222    // This case agrees with FireFox and the spec, but not with the old polyfill or Blink. The old
223    // polyfill only does matrix decomposition on the rotate section of the function
224    // lists.
225    interp = webAnimations1.propertyInterpolation(
226        'transform',
227        'translate(0px)',
228        'translate(800px) rotate(9rad)');
229    evaluatedInterp = interp(0.4);
230    compareMatrices(evaluatedInterp, [0.47, 0.89, -0.89, 0.47, 320, 0], 6);
231
232    interp = webAnimations1.propertyInterpolation(
233        'transform',
234        'translate(0px, 0px) rotate(0deg) scale(1)',
235        'translate(900px, 190px) scale(3) rotate(9rad)');
236    evaluatedInterp = interp(0.4);
237    compareMatrices(evaluatedInterp, [0.84, 1.59, -1.59, 0.84, 360, 76], 6);
238
239    interp = webAnimations1.propertyInterpolation(
240        'transform',
241        'perspective(1000px)',
242        'perspective(200px)');
243    evaluatedInterp = interp(0.2);
244    compareMatrices(evaluatedInterp, [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, -0.0018, 0, 0, 0, 1], 16);
245  });
246
247  test('transforms that decompose to a 2D matrix result in a 2D matrix transform in computed style', function() {
248    var target = document.createElement('div');
249    document.body.appendChild(target);
250
251    var player = target.animate(
252        [{transform: 'translate(100px)'},
253         {transform: 'rotate(45deg)'}],
254        2000);
255    player.currentTime = 500;
256    player.pause();
257
258    var styleTransform = getComputedStyle(target).transform || getComputedStyle(target).webkitTransform;
259    var elements = styleTransform.slice(
260        styleTransform.indexOf('(') + 1, styleTransform.lastIndexOf(')')).split(',');
261    assert.equal(elements.length, 6);
262  });
263
264  test('decompose various CSS properties', function() {
265    var interp = webAnimations1.propertyInterpolation(
266        'transform',
267        'rotateX(110deg)',
268        'rotateX(10deg) matrix(1, 0, 0, 1, 0, 0)');
269    var evaluatedInterp = interp(0.5);
270    compareMatrices(evaluatedInterp, [1, 0, 0, 0, 0, 0.500, 0.866, 0, 0, -0.866, 0.500, 0, 0, 0, 0, 1], 16);
271
272    // FIXME: This test case differs from blink transitions which gives -1(this)
273    // This case agrees with FireFox transitions.
274    interp = webAnimations1.propertyInterpolation(
275        'transform',
276        'rotateY(10rad)',
277        'rotateY(2rad) matrix(1, 0, 0, 1, 0, 0)');
278    evaluatedInterp = interp(0.5);
279    compareMatrices(evaluatedInterp, [0.960, 0, 0.279, 0, 0, 1, 0, 0, -0.279, 0, 0.960, 0, 0, 0, 0, 1], 16);
280
281    interp = webAnimations1.propertyInterpolation(
282        'transform',
283        'rotate(320deg)',
284        'rotate(10deg) matrix(1, 0, 0, 1, 0, 0)');
285    evaluatedInterp = interp(0.5);
286    compareMatrices(evaluatedInterp, [0.966, -0.259, 0.259, 0.966, 0, 0], 6);
287
288    // FIXME: This test case differs from blink transitions which gives -1(this)
289    // This case agrees with FireFox transitions.
290    interp = webAnimations1.propertyInterpolation(
291        'transform',
292        'rotateZ(10rad)',
293        'rotateZ(2rad) matrix(1, 0, 0, 1, 0, 0)');
294    evaluatedInterp = interp(0.5);
295    compareMatrices(evaluatedInterp, [0.960, -0.279, 0.279, 0.960, 0, 0], 6);
296
297    // FIXME: This test case differs from blink transitions
298    // which gives matrix3d(-0.24, +0.91, +0.33, +0, +0.33, -0.24, +0.91, +0, +0.91, +0.33, -0.24, +0, +0, +0, +0, +1)
299    // versus our  matrix3d(+0.91, -0.24, +0.33, +0, +0.33, +0.91, -0.24, +0, -0.24, +0.33, +0.91, +0, +0, +0, +0, +1)
300    // This case agrees with FireFox transitions.
301    interp = webAnimations1.propertyInterpolation(
302        'transform',
303        'rotate3d(1, 1, 1, 100deg)',
304        'rotate3d(1, 1, 1, 200deg) matrix(1, 0, 0, 1, 0, 0)');
305    evaluatedInterp = interp(0.5);
306    compareMatrices(evaluatedInterp, [0.911, -0.244, 0.333, 0, 0.333, 0.911, -0.244, 0, -0.244, 0.333, 0.911, 0, 0, 0, 0, 1], 16);
307
308    interp = webAnimations1.propertyInterpolation(
309        'transform',
310        'scale(10)',
311        'scale(2) matrix(1, 0, 0, 1, 0, 0)');
312    evaluatedInterp = interp(0.5);
313    compareMatrices(evaluatedInterp, [6, 0, 0, 6, 0, 0], 6);
314
315    interp = webAnimations1.propertyInterpolation(
316        'transform',
317        'scalex(10)',
318        'scalex(2) matrix(1, 0, 0, 1, 0, 0)');
319    evaluatedInterp = interp(0.5);
320    compareMatrices(evaluatedInterp, [6, 0, 0, 1, 0, 0], 6);
321
322    interp = webAnimations1.propertyInterpolation(
323        'transform',
324        'scaley(10)',
325        'scaley(2) matrix(1, 0, 0, 1, 0, 0)');
326    evaluatedInterp = interp(0.5);
327    compareMatrices(evaluatedInterp, [1, 0, 0, 6, 0, 0], 6);
328
329    interp = webAnimations1.propertyInterpolation(
330        'transform',
331        'scalez(10)',
332        'scalez(2) matrix(1, 0, 0, 1, 0, 0)');
333    evaluatedInterp = interp(0.5);
334    compareMatrices(evaluatedInterp, [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 6, 0, 0, 0, 0, 1], 16);
335
336    interp = webAnimations1.propertyInterpolation(
337        'transform',
338        'scale3d(6, 8, 10)',
339        'scale3d(2, 2, 2) matrix(1, 0, 0, 1, 0, 0)');
340    evaluatedInterp = interp(0.5);
341    compareMatrices(evaluatedInterp, [4, 0, 0, 0, 0, 5, 0, 0, 0, 0, 6, 0, 0, 0, 0, 1], 16);
342
343    interp = webAnimations1.propertyInterpolation(
344        'transform',
345        'skew(30deg)',
346        'skew(0deg) matrix(1, 0, 0, 1, 0, 0)');
347    evaluatedInterp = interp(0.5);
348    compareMatrices(evaluatedInterp, [1, 0, 0.289, 1, 0, 0], 6);
349
350    interp = webAnimations1.propertyInterpolation(
351        'transform',
352        'skewx(3rad)',
353        'skewx(1rad) matrix(1, 0, 0, 1, 0, 0)');
354    evaluatedInterp = interp(0.5);
355    compareMatrices(evaluatedInterp, [1, 0, 0.707, 1, 0, 0], 6);
356
357    interp = webAnimations1.propertyInterpolation(
358        'transform',
359        'skewy(3rad)',
360        'skewy(1rad) matrix(1, 0, 0, 1, 0, 0)');
361    evaluatedInterp = interp(0.5);
362    compareMatrices(evaluatedInterp, [1.301, 0.595, 0.174, 0.921, 0, 0], 6);
363
364    interp = webAnimations1.propertyInterpolation(
365        'transform',
366        'translate(10px, 20px)',
367        'translate(100px, 200px) matrix(1, 0, 0, 1, 0, 0)');
368    evaluatedInterp = interp(0.5);
369    compareMatrices(evaluatedInterp, [1, 0, 0, 1, 55, 110], 6);
370
371    interp = webAnimations1.propertyInterpolation(
372        'transform',
373        'translatex(10px)',
374        'translatex(100px) matrix(1, 0, 0, 1, 0, 0)');
375    evaluatedInterp = interp(0.5);
376    compareMatrices(evaluatedInterp, [1, 0, 0, 1, 55, 0], 6);
377
378    interp = webAnimations1.propertyInterpolation(
379        'transform',
380        'translatey(10px)',
381        'translatey(100px) matrix(1, 0, 0, 1, 0, 0)');
382    evaluatedInterp = interp(0.5);
383    compareMatrices(evaluatedInterp, [1, 0, 0, 1, 0, 55], 6);
384
385    interp = webAnimations1.propertyInterpolation(
386        'transform',
387        'translatez(20px)',
388        'translatez(200px) matrix(1, 0, 0, 1, 0, 0)');
389    evaluatedInterp = interp(0.5);
390    compareMatrices(evaluatedInterp, [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 110, 1], 16);
391
392    interp = webAnimations1.propertyInterpolation(
393        'transform',
394        'translate3d(10px, 10px, 10px)',
395        'translate3d(20px, 20px, 20px) matrix(1, 0, 0, 1, 0, 0)');
396    evaluatedInterp = interp(0.5);
397    compareMatrices(evaluatedInterp, [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 15, 15, 15, 1], 16);
398
399    interp = webAnimations1.propertyInterpolation(
400        'transform',
401        'perspective(300px)',
402        'perspective(900px) matrix(1, 0, 0, 1, 0, 0)');
403    evaluatedInterp = interp(0.5);
404    compareMatrices(evaluatedInterp, [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, -0.002222, 0, 0, 0, 1], 16);
405  });
406
407  test('decompose various CSS properties with unsupported units', function() {
408    compareInterpolatedTransforms(
409        ['rotateX(110grad)', 'rotateX(10deg) matrix(1, 0, 0, 1, 0, 0)'],
410        ['rotateX(0deg)', 'rotateX(10deg) matrix(1, 0, 0, 1, 0, 0)'],
411        0.5);
412
413    compareInterpolatedTransforms(
414        ['rotateY(2turn)', 'rotateY(2rad) matrix(1, 0, 0, 1, 0, 0)'],
415        ['rotateY(0rad)', 'rotateY(2rad) matrix(1, 0, 0, 1, 0, 0)'],
416        0.5);
417
418    compareInterpolatedTransforms(
419        ['rotate(320deg)', 'rotateY(10grad) matrix(1, 0, 0, 1, 0, 0)'],
420        ['rotate(320deg)', 'rotateY(0deg) matrix(1, 0, 0, 1, 0, 0)'],
421        0.5);
422
423    compareInterpolatedTransforms(
424        ['rotateZ(10grad)', 'rotateZ(2rad) matrix(1, 0, 0, 1, 0, 0)'],
425        ['rotateZ(0rad)', 'rotateZ(2rad) matrix(1, 0, 0, 1, 0, 0)'],
426        0.5);
427
428    compareInterpolatedTransforms(
429        ['rotate3d(1, 1, 1, 100deg)', 'rotate3d(1, 1, 1, 2turn) matrix(1, 0, 0, 1, 0, 0)'],
430        ['rotate3d(1, 1, 1, 100deg)', 'rotate3d(1, 1, 1, 0deg) matrix(1, 0, 0, 1, 0, 0)'],
431        0.5);
432
433    compareInterpolatedTransforms(
434        ['skew(30grad)', 'skew(10deg) matrix(1, 0, 0, 1, 0, 0)'],
435        ['skew(0deg)', 'skew(10deg) matrix(1, 0, 0, 1, 0, 0)'],
436        0.5);
437
438    compareInterpolatedTransforms(
439        ['skewx(3grad)', 'skewx(1rad) matrix(1, 0, 0, 1, 0, 0)'],
440        ['skewx(0rad)', 'skewx(1rad) matrix(1, 0, 0, 1, 0, 0)'],
441        0.5);
442
443    compareInterpolatedTransforms(
444        ['skewy(3rad)', 'skewy(1grad) matrix(1, 0, 0, 1, 0, 0)'],
445        ['skewy(3rad)', 'skewy(0rad) matrix(1, 0, 0, 1, 0, 0)'],
446        0.5);
447
448    compareInterpolatedTransforms(
449        ['translate(10in, 20in)', 'translate(100px, 200px) matrix(1, 0, 0, 1, 0, 0)'],
450        ['translate(0px, 0px)', 'translate(100px, 200px) matrix(1, 0, 0, 1, 0, 0)'],
451        0.5);
452
453    compareInterpolatedTransforms(
454        ['translatex(20in)', 'translatex(200px) matrix(1, 0, 0, 1, 0, 0)'],
455        ['translatex(0px)', 'translatex(200px) matrix(1, 0, 0, 1, 0, 0)'],
456        0.5);
457
458    compareInterpolatedTransforms(
459        ['translatey(10in)', 'translatey(100px) matrix(1, 0, 0, 1, 0, 0)'],
460        ['translatey(0px)', 'translatey(100px) matrix(1, 0, 0, 1, 0, 0)'],
461        0.5);
462
463    compareInterpolatedTransforms(
464        ['translatez(10em)', 'translatez(100px) matrix(1, 0, 0, 1, 0, 0)'],
465        ['translatez(0px)', 'translatez(100px) matrix(1, 0, 0, 1, 0, 0)'],
466        0.5);
467
468    compareInterpolatedTransforms(
469        ['translate3d(10px, 10px, 10px)', 'translate3d(2rem, 2rem, 2rem) matrix(1, 0, 0, 1, 0, 0)'],
470        ['translate3d(10px, 10px, 10px)', 'translate3d(0px, 0px, 0px) matrix(1, 0, 0, 1, 0, 0)'],
471        0.5);
472
473    compareInterpolatedTransforms(
474        ['perspective(300px)', 'perspective(9em) matrix(1, 0, 0, 1, 0, 0)'],
475        ['perspective(300px)', 'perspective(0px) matrix(1, 0, 0, 1, 0, 0)'],
476        0.5);
477  });
478
479  test('transform interpolations involving matrices when matrix code is not available', function() {
480    // FIXME: This is vulnerable to module interface changes. Can we disable modules?
481    var composeMatrix = webAnimations1.composeMatrix;
482    var quat = webAnimations1.quat;
483    var dot = webAnimations1.dot;
484    var makeMatrixDecomposition = webAnimations1.makeMatrixDecomposition;
485    webAnimations1.composeMatrix = undefined;
486    webAnimations1.quat = undefined;
487    webAnimations1.dot = undefined;
488    webAnimations1.makeMatrixDecomposition = undefined;
489
490    var testFlipTransformLists = function(keyframeFrom, keyframeTo) {
491      var interp = webAnimations1.propertyInterpolation(
492          'transform',
493          keyframeFrom,
494          keyframeTo);
495      var evaluatedInterp = interp(0.49);
496      assert.equal(evaluatedInterp, keyframeFrom);
497      evaluatedInterp = interp(0.51);
498      assert.equal(evaluatedInterp, keyframeTo);
499    };
500
501    try {
502      // Function lists with just matrices.
503      testFlipTransformLists('matrix(1, 0, 0, 1, 0, 0)', 'matrix(1, -0.2, 0, 1, 0, 0)');
504      // Function lists with matrices and other functions.
505      testFlipTransformLists(
506          'translate(100px) matrix(1, 0, 0, 1, 0, 0) rotate(10deg)',
507          'translate(10px) matrix(1, -0.2, 0, 1, 0, 0) rotate(100deg)');
508      // Function lists that require matrix decomposition to be interpolated.
509      testFlipTransformLists('translate(10px)', 'scale(2)');
510      testFlipTransformLists('scale(2)', 'translate(10px)');
511      testFlipTransformLists('rotateX(10deg)', 'rotateY(20deg)');
512      testFlipTransformLists('rotateX(10deg)', 'translate(10px) rotateX(200deg)');
513      testFlipTransformLists(
514          'rotate(0rad) translate(0px)',
515          'translate(800px) rotate(9rad)');
516      testFlipTransformLists(
517          'translate(0px, 0px) rotate(0deg) scale(1)',
518          'scale(3) translate(300px, 90px) rotate(9rad)');
519      testFlipTransformLists(
520          'translate(0px, 0px) skew(30deg)',
521          'skew(0deg) translate(300px, 90px)');
522      testFlipTransformLists(
523          'matrix(1, 0, 0, 1, 0, 0) translate(100px)',
524          'translate(10px) matrix(1, -0.2, 0, 1, 0, 0)');
525    } finally {
526      webAnimations1.composeMatrix = composeMatrix;
527      webAnimations1.quat = quat;
528      webAnimations1.dot = dot;
529      webAnimations1.makeMatrixDecomposition = makeMatrixDecomposition;
530    }
531  });
532});
533