517 lines
14 KiB
JavaScript
517 lines
14 KiB
JavaScript
/**
|
|
* Copyright (c) 2015-present, Facebook, Inc.
|
|
* All rights reserved.
|
|
*
|
|
* This source code is licensed under the BSD-style license found in the
|
|
* LICENSE file in the root directory of this source tree. An additional grant
|
|
* of patent rights can be found in the PATENTS file in the same directory.
|
|
*/
|
|
'use strict';
|
|
|
|
jest
|
|
.autoMockOff()
|
|
.setMock('Text', {})
|
|
.setMock('View', {})
|
|
.setMock('Image', {})
|
|
.setMock('React', {Component: class {}});
|
|
|
|
var Animated = require('Animated');
|
|
|
|
describe('Animated', () => {
|
|
it('works end to end', () => {
|
|
var anim = new Animated.Value(0);
|
|
|
|
var callback = jest.genMockFunction();
|
|
|
|
var node = new Animated.__PropsOnlyForTests({
|
|
style: {
|
|
backgroundColor: 'red',
|
|
opacity: anim,
|
|
transform: [
|
|
{translateX: anim.interpolate({
|
|
inputRange: [0, 1],
|
|
outputRange: [100, 200],
|
|
})},
|
|
{scale: anim},
|
|
]
|
|
}
|
|
}, callback);
|
|
|
|
expect(anim.__getChildren().length).toBe(3);
|
|
|
|
expect(node.__getValue()).toEqual({
|
|
style: {
|
|
backgroundColor: 'red',
|
|
opacity: 0,
|
|
transform: [
|
|
{translateX: 100},
|
|
{scale: 0},
|
|
],
|
|
},
|
|
});
|
|
|
|
anim.setValue(0.5);
|
|
|
|
expect(callback).toBeCalled();
|
|
|
|
expect(node.__getValue()).toEqual({
|
|
style: {
|
|
backgroundColor: 'red',
|
|
opacity: 0.5,
|
|
transform: [
|
|
{translateX: 150},
|
|
{scale: 0.5},
|
|
],
|
|
},
|
|
});
|
|
|
|
node.__detach();
|
|
expect(anim.__getChildren().length).toBe(0);
|
|
|
|
anim.setValue(1);
|
|
expect(callback.mock.calls.length).toBe(1);
|
|
});
|
|
|
|
it('does not detach on updates', () => {
|
|
var anim = new Animated.Value(0);
|
|
anim.__detach = jest.genMockFunction();
|
|
|
|
var c = new Animated.View();
|
|
c.props = {
|
|
style: {
|
|
opacity: anim,
|
|
},
|
|
};
|
|
c.componentWillMount();
|
|
|
|
expect(anim.__detach).not.toBeCalled();
|
|
c.componentWillReceiveProps({
|
|
style: {
|
|
opacity: anim,
|
|
},
|
|
});
|
|
expect(anim.__detach).not.toBeCalled();
|
|
|
|
c.componentWillUnmount();
|
|
expect(anim.__detach).toBeCalled();
|
|
});
|
|
|
|
|
|
it('stops animation when detached', () => {
|
|
// jest environment doesn't have requestAnimationFrame :(
|
|
window.requestAnimationFrame = jest.genMockFunction();
|
|
window.cancelAnimationFrame = jest.genMockFunction();
|
|
|
|
var anim = new Animated.Value(0);
|
|
var callback = jest.genMockFunction();
|
|
|
|
var c = new Animated.View();
|
|
c.props = {
|
|
style: {
|
|
opacity: anim,
|
|
},
|
|
};
|
|
c.componentWillMount();
|
|
|
|
Animated.timing(anim, {toValue: 10, duration: 1000}).start(callback);
|
|
|
|
c.componentWillUnmount();
|
|
|
|
expect(callback).toBeCalledWith({finished: false});
|
|
expect(callback).toBeCalledWith({finished: false});
|
|
});
|
|
|
|
it('triggers callback when spring is at rest', () => {
|
|
var anim = new Animated.Value(0);
|
|
var callback = jest.genMockFunction();
|
|
Animated.spring(anim, {toValue: 0, velocity: 0}).start(callback);
|
|
expect(callback).toBeCalled();
|
|
});
|
|
|
|
it('send toValue when a spring stops', () => {
|
|
var anim = new Animated.Value(0);
|
|
var listener = jest.genMockFunction();
|
|
anim.addListener(listener);
|
|
Animated.spring(anim, {toValue: 15}).start();
|
|
jest.runAllTimers();
|
|
var lastValue = listener.mock.calls[listener.mock.calls.length - 2][0].value;
|
|
expect(lastValue).not.toBe(15);
|
|
expect(lastValue).toBeCloseTo(15);
|
|
expect(anim.__getValue()).toBe(15);
|
|
});
|
|
|
|
});
|
|
|
|
|
|
describe('Animated Sequence', () => {
|
|
|
|
it('works with an empty sequence', () => {
|
|
var cb = jest.genMockFunction();
|
|
Animated.sequence([]).start(cb);
|
|
expect(cb).toBeCalledWith({finished: true});
|
|
});
|
|
|
|
it('sequences well', () => {
|
|
var anim1 = {start: jest.genMockFunction()};
|
|
var anim2 = {start: jest.genMockFunction()};
|
|
var cb = jest.genMockFunction();
|
|
|
|
var seq = Animated.sequence([anim1, anim2]);
|
|
|
|
expect(anim1.start).not.toBeCalled();
|
|
expect(anim2.start).not.toBeCalled();
|
|
|
|
seq.start(cb);
|
|
|
|
expect(anim1.start).toBeCalled();
|
|
expect(anim2.start).not.toBeCalled();
|
|
expect(cb).not.toBeCalled();
|
|
|
|
anim1.start.mock.calls[0][0]({finished: true});
|
|
|
|
expect(anim2.start).toBeCalled();
|
|
expect(cb).not.toBeCalled();
|
|
|
|
anim2.start.mock.calls[0][0]({finished: true});
|
|
expect(cb).toBeCalledWith({finished: true});
|
|
});
|
|
|
|
it('supports interrupting sequence', () => {
|
|
var anim1 = {start: jest.genMockFunction()};
|
|
var anim2 = {start: jest.genMockFunction()};
|
|
var cb = jest.genMockFunction();
|
|
|
|
Animated.sequence([anim1, anim2]).start(cb);
|
|
|
|
anim1.start.mock.calls[0][0]({finished: false});
|
|
|
|
expect(anim1.start).toBeCalled();
|
|
expect(anim2.start).not.toBeCalled();
|
|
expect(cb).toBeCalledWith({finished: false});
|
|
});
|
|
|
|
it('supports stopping sequence', () => {
|
|
var anim1 = {start: jest.genMockFunction(), stop: jest.genMockFunction()};
|
|
var anim2 = {start: jest.genMockFunction(), stop: jest.genMockFunction()};
|
|
var cb = jest.genMockFunction();
|
|
|
|
var seq = Animated.sequence([anim1, anim2]);
|
|
seq.start(cb);
|
|
seq.stop();
|
|
|
|
expect(anim1.stop).toBeCalled();
|
|
expect(anim2.stop).not.toBeCalled();
|
|
expect(cb).not.toBeCalled();
|
|
|
|
anim1.start.mock.calls[0][0]({finished: false});
|
|
|
|
expect(cb).toBeCalledWith({finished: false});
|
|
});
|
|
});
|
|
|
|
|
|
describe('Animated Parallel', () => {
|
|
|
|
it('works with an empty parallel', () => {
|
|
var cb = jest.genMockFunction();
|
|
Animated.parallel([]).start(cb);
|
|
expect(cb).toBeCalledWith({finished: true});
|
|
});
|
|
|
|
it('works with an empty element in array', () => {
|
|
var anim1 = {start: jest.genMockFunction()};
|
|
var cb = jest.genMockFunction();
|
|
Animated.parallel([null, anim1]).start(cb);
|
|
|
|
expect(anim1.start).toBeCalled();
|
|
anim1.start.mock.calls[0][0]({finished: true});
|
|
|
|
expect(cb).toBeCalledWith({finished: true});
|
|
});
|
|
|
|
it('parellelizes well', () => {
|
|
var anim1 = {start: jest.genMockFunction()};
|
|
var anim2 = {start: jest.genMockFunction()};
|
|
var cb = jest.genMockFunction();
|
|
|
|
var par = Animated.parallel([anim1, anim2]);
|
|
|
|
expect(anim1.start).not.toBeCalled();
|
|
expect(anim2.start).not.toBeCalled();
|
|
|
|
par.start(cb);
|
|
|
|
expect(anim1.start).toBeCalled();
|
|
expect(anim2.start).toBeCalled();
|
|
expect(cb).not.toBeCalled();
|
|
|
|
anim1.start.mock.calls[0][0]({finished: true});
|
|
expect(cb).not.toBeCalled();
|
|
|
|
anim2.start.mock.calls[0][0]({finished: true});
|
|
expect(cb).toBeCalledWith({finished: true});
|
|
});
|
|
|
|
it('supports stopping parallel', () => {
|
|
var anim1 = {start: jest.genMockFunction(), stop: jest.genMockFunction()};
|
|
var anim2 = {start: jest.genMockFunction(), stop: jest.genMockFunction()};
|
|
var cb = jest.genMockFunction();
|
|
|
|
var seq = Animated.parallel([anim1, anim2]);
|
|
seq.start(cb);
|
|
seq.stop();
|
|
|
|
expect(anim1.stop).toBeCalled();
|
|
expect(anim2.stop).toBeCalled();
|
|
expect(cb).not.toBeCalled();
|
|
|
|
anim1.start.mock.calls[0][0]({finished: false});
|
|
expect(cb).not.toBeCalled();
|
|
|
|
anim2.start.mock.calls[0][0]({finished: false});
|
|
expect(cb).toBeCalledWith({finished: false});
|
|
});
|
|
|
|
|
|
it('does not call stop more than once when stopping', () => {
|
|
var anim1 = {start: jest.genMockFunction(), stop: jest.genMockFunction()};
|
|
var anim2 = {start: jest.genMockFunction(), stop: jest.genMockFunction()};
|
|
var anim3 = {start: jest.genMockFunction(), stop: jest.genMockFunction()};
|
|
var cb = jest.genMockFunction();
|
|
|
|
var seq = Animated.parallel([anim1, anim2, anim3]);
|
|
seq.start(cb);
|
|
|
|
anim1.start.mock.calls[0][0]({finished: false});
|
|
|
|
expect(anim1.stop.mock.calls.length).toBe(0);
|
|
expect(anim2.stop.mock.calls.length).toBe(1);
|
|
expect(anim3.stop.mock.calls.length).toBe(1);
|
|
|
|
anim2.start.mock.calls[0][0]({finished: false});
|
|
|
|
expect(anim1.stop.mock.calls.length).toBe(0);
|
|
expect(anim2.stop.mock.calls.length).toBe(1);
|
|
expect(anim3.stop.mock.calls.length).toBe(1);
|
|
|
|
anim3.start.mock.calls[0][0]({finished: false});
|
|
|
|
expect(anim1.stop.mock.calls.length).toBe(0);
|
|
expect(anim2.stop.mock.calls.length).toBe(1);
|
|
expect(anim3.stop.mock.calls.length).toBe(1);
|
|
});
|
|
});
|
|
|
|
describe('Animated delays', () => {
|
|
it('should call anim after delay in sequence', () => {
|
|
var anim = {start: jest.genMockFunction(), stop: jest.genMockFunction()};
|
|
var cb = jest.genMockFunction();
|
|
Animated.sequence([
|
|
Animated.delay(1000),
|
|
anim,
|
|
]).start(cb);
|
|
jest.runAllTimers();
|
|
expect(anim.start.mock.calls.length).toBe(1);
|
|
expect(cb).not.toBeCalled();
|
|
anim.start.mock.calls[0][0]({finished: true});
|
|
expect(cb).toBeCalledWith({finished: true});
|
|
});
|
|
it('should run stagger to end', () => {
|
|
var cb = jest.genMockFunction();
|
|
Animated.stagger(1000, [
|
|
Animated.delay(1000),
|
|
Animated.delay(1000),
|
|
Animated.delay(1000),
|
|
]).start(cb);
|
|
jest.runAllTimers();
|
|
expect(cb).toBeCalledWith({finished: true});
|
|
});
|
|
});
|
|
|
|
describe('Animated Events', () => {
|
|
it('should map events', () => {
|
|
var value = new Animated.Value(0);
|
|
var handler = Animated.event(
|
|
[null, {state: {foo: value}}],
|
|
);
|
|
handler({bar: 'ignoreBar'}, {state: {baz: 'ignoreBaz', foo: 42}});
|
|
expect(value.__getValue()).toBe(42);
|
|
});
|
|
it('should call listeners', () => {
|
|
var value = new Animated.Value(0);
|
|
var listener = jest.genMockFunction();
|
|
var handler = Animated.event(
|
|
[{foo: value}],
|
|
{listener},
|
|
);
|
|
handler({foo: 42});
|
|
expect(value.__getValue()).toBe(42);
|
|
expect(listener.mock.calls.length).toBe(1);
|
|
expect(listener).toBeCalledWith({foo: 42});
|
|
});
|
|
});
|
|
|
|
describe('Animated Tracking', () => {
|
|
it('should track values', () => {
|
|
var value1 = new Animated.Value(0);
|
|
var value2 = new Animated.Value(0);
|
|
Animated.timing(value2, {
|
|
toValue: value1,
|
|
duration: 0,
|
|
}).start();
|
|
value1.setValue(42);
|
|
expect(value2.__getValue()).toBe(42);
|
|
value1.setValue(7);
|
|
expect(value2.__getValue()).toBe(7);
|
|
});
|
|
|
|
it('should track interpolated values', () => {
|
|
var value1 = new Animated.Value(0);
|
|
var value2 = new Animated.Value(0);
|
|
Animated.timing(value2, {
|
|
toValue: value1.interpolate({
|
|
inputRange: [0, 2],
|
|
outputRange: [0, 1]
|
|
}),
|
|
duration: 0,
|
|
}).start();
|
|
value1.setValue(42);
|
|
expect(value2.__getValue()).toBe(42 / 2);
|
|
});
|
|
|
|
it('should stop tracking when animated', () => {
|
|
var value1 = new Animated.Value(0);
|
|
var value2 = new Animated.Value(0);
|
|
Animated.timing(value2, {
|
|
toValue: value1,
|
|
duration: 0,
|
|
}).start();
|
|
value1.setValue(42);
|
|
expect(value2.__getValue()).toBe(42);
|
|
Animated.timing(value2, {
|
|
toValue: 7,
|
|
duration: 0,
|
|
}).start();
|
|
value1.setValue(1492);
|
|
expect(value2.__getValue()).toBe(7);
|
|
});
|
|
});
|
|
|
|
describe('Animated Vectors', () => {
|
|
it('should animate vectors', () => {
|
|
var vec = new Animated.ValueXY();
|
|
|
|
var callback = jest.genMockFunction();
|
|
|
|
var node = new Animated.__PropsOnlyForTests({
|
|
style: {
|
|
opacity: vec.x.interpolate({
|
|
inputRange: [0, 42],
|
|
outputRange: [0.2, 0.8],
|
|
}),
|
|
transform: vec.getTranslateTransform(),
|
|
...vec.getLayout(),
|
|
}
|
|
}, callback);
|
|
|
|
expect(node.__getValue()).toEqual({
|
|
style: {
|
|
opacity: 0.2,
|
|
transform: [
|
|
{translateX: 0},
|
|
{translateY: 0},
|
|
],
|
|
left: 0,
|
|
top: 0,
|
|
},
|
|
});
|
|
|
|
vec.setValue({x: 42, y: 1492});
|
|
|
|
expect(callback.mock.calls.length).toBe(2); // once each for x, y
|
|
|
|
expect(node.__getValue()).toEqual({
|
|
style: {
|
|
opacity: 0.8,
|
|
transform: [
|
|
{translateX: 42},
|
|
{translateY: 1492},
|
|
],
|
|
left: 42,
|
|
top: 1492,
|
|
},
|
|
});
|
|
|
|
node.__detach();
|
|
|
|
vec.setValue({x: 1, y: 1});
|
|
expect(callback.mock.calls.length).toBe(2);
|
|
});
|
|
|
|
it('should track vectors', () => {
|
|
var value1 = new Animated.ValueXY();
|
|
var value2 = new Animated.ValueXY();
|
|
Animated.timing(value2, {
|
|
toValue: value1,
|
|
duration: 0,
|
|
}).start();
|
|
value1.setValue({x: 42, y: 1492});
|
|
expect(value2.__getValue()).toEqual({x: 42, y: 1492});
|
|
|
|
// Make sure tracking keeps working (see stopTogether in ParallelConfig used
|
|
// by maybeVectorAnim).
|
|
value1.setValue({x: 3, y: 4});
|
|
expect(value2.__getValue()).toEqual({x: 3, y: 4});
|
|
});
|
|
|
|
it('should track with springs', () => {
|
|
var value1 = new Animated.ValueXY();
|
|
var value2 = new Animated.ValueXY();
|
|
Animated.spring(value2, {
|
|
toValue: value1,
|
|
tension: 3000, // faster spring for faster test
|
|
friction: 60,
|
|
}).start();
|
|
value1.setValue({x: 1, y: 1});
|
|
jest.runAllTimers();
|
|
expect(Math.round(value2.__getValue().x)).toEqual(1);
|
|
expect(Math.round(value2.__getValue().y)).toEqual(1);
|
|
value1.setValue({x: 2, y: 2});
|
|
jest.runAllTimers();
|
|
expect(Math.round(value2.__getValue().x)).toEqual(2);
|
|
expect(Math.round(value2.__getValue().y)).toEqual(2);
|
|
});
|
|
});
|
|
|
|
describe('Animated Listeners', () => {
|
|
it('should get updates', () => {
|
|
var value1 = new Animated.Value(0);
|
|
var listener = jest.genMockFunction();
|
|
var id = value1.addListener(listener);
|
|
value1.setValue(42);
|
|
expect(listener.mock.calls.length).toBe(1);
|
|
expect(listener).toBeCalledWith({value: 42});
|
|
expect(value1.__getValue()).toBe(42);
|
|
value1.setValue(7);
|
|
expect(listener.mock.calls.length).toBe(2);
|
|
expect(listener).toBeCalledWith({value: 7});
|
|
expect(value1.__getValue()).toBe(7);
|
|
value1.removeListener(id);
|
|
value1.setValue(1492);
|
|
expect(listener.mock.calls.length).toBe(2);
|
|
expect(value1.__getValue()).toBe(1492);
|
|
});
|
|
|
|
it('should removeAll', () => {
|
|
var value1 = new Animated.Value(0);
|
|
var listener = jest.genMockFunction();
|
|
[1,2,3,4].forEach(() => value1.addListener(listener));
|
|
value1.setValue(42);
|
|
expect(listener.mock.calls.length).toBe(4);
|
|
expect(listener).toBeCalledWith({value: 42});
|
|
value1.removeAllListeners();
|
|
value1.setValue(7);
|
|
expect(listener.mock.calls.length).toBe(4);
|
|
});
|
|
});
|