UNPKG

5.99 kBJavaScriptView Raw
1import Animated, { Easing } from './Animated';
2import ReanimatedModule from './ReanimatedModule';
3import React from 'react';
4
5import renderer from 'react-test-renderer';
6
7jest.mock('./ReanimatedEventEmitter');
8jest.mock('./ReanimatedModule');
9jest.mock('./derived/evaluateOnce');
10jest.mock('./core/AnimatedProps');
11
12const { Value, timing, spring, decay } = Animated;
13describe('Reanimated backward compatible API', () => {
14 beforeEach(() => {
15 let numberOfNodes = 0;
16 ReanimatedModule.createNode = () => numberOfNodes++;
17 ReanimatedModule.dropNode = () => numberOfNodes--;
18 ReanimatedModule.getNumberOfNodes = () => numberOfNodes;
19 });
20
21 const checkIfNodesGetDetachedCorrectly = animation => {
22 class TestComponent extends React.Component {
23 constructor(props) {
24 super(props);
25 this.transX = new Value(0);
26 this.anim = animation.node(this.transX, animation.config);
27 }
28
29 start(method) {
30 this.anim.start(method);
31 }
32
33 stop(res) {
34 this.anim.__stopImmediately_testOnly(res);
35 }
36
37 render() {
38 return (
39 <Animated.View style={{ transform: [{ translateX: this.transX }] }} />
40 );
41 }
42 }
43 const ref = React.createRef();
44 let result;
45 const resMethod = ({ finished }) => (result = finished);
46 const initial = ReanimatedModule.getNumberOfNodes();
47 const wrapper = renderer.create(<TestComponent ref={ref} />);
48 const before = ReanimatedModule.getNumberOfNodes();
49 ref.current.start(resMethod);
50 const during = ReanimatedModule.getNumberOfNodes();
51 ref.current.stop(true);
52 const after = ReanimatedModule.getNumberOfNodes();
53 wrapper.unmount();
54 const final = ReanimatedModule.getNumberOfNodes();
55
56 return (
57 result &&
58 initial === final &&
59 after === before &&
60 during > after &&
61 initial === 0 &&
62 before === 4
63 );
64 };
65
66 it('fails if timing does not attach nodes correctly', () => {
67 expect(
68 checkIfNodesGetDetachedCorrectly({
69 node: timing,
70 name: 'timing',
71 config: {
72 duration: 5000,
73 toValue: 120,
74 easing: Easing.inOut(Easing.ease),
75 },
76 })
77 ).toBeTruthy();
78 });
79
80 it('fails if decay does not attach nodes correctly', () => {
81 expect(
82 checkIfNodesGetDetachedCorrectly({
83 node: decay,
84 name: 'decay',
85 config: {
86 deceleration: 0.997,
87 },
88 })
89 ).toBeTruthy();
90 });
91
92 it('fails if spring does not attach nodes correctly', () => {
93 expect(
94 checkIfNodesGetDetachedCorrectly({
95 node: spring,
96 name: 'spring',
97 config: {
98 toValue: 0,
99 damping: 7,
100 mass: 1,
101 stiffness: 121.6,
102 overshootClamping: false,
103 restSpeedThreshold: 0.001,
104 restDisplacementThreshold: 0.001,
105 },
106 })
107 ).toBeTruthy();
108 });
109
110 it('fails if animation related nodes are still attached after detaching of value with two animations triggered', () => {
111 const { timing, Value } = Animated;
112 class TestComponent extends React.Component {
113 constructor(props) {
114 super(props);
115 this.transX = new Value(0);
116 const config = {
117 duration: 5000,
118 toValue: -120,
119 easing: Easing.inOut(Easing.ease),
120 };
121 this.anim = timing(this.transX, config);
122 this.anim2 = timing(this.transX, config);
123 }
124
125 start1(method) {
126 this.anim.start(method);
127 }
128
129 start2(method) {
130 this.anim2.start(method);
131 }
132
133 render() {
134 return (
135 <Animated.View style={{ transform: [{ translateX: this.transX }] }} />
136 );
137 }
138 }
139 const ref = React.createRef();
140 const wrapper = renderer.create(<TestComponent ref={ref} />);
141 let result = true;
142 const resMethod = ({ finished }) => (result = finished);
143 ref.current.start1(resMethod);
144 ref.current.start2(resMethod);
145 expect(result).toBeFalsy();
146 result = true;
147 const numberOfNodesBeforeUnmounting = ReanimatedModule.getNumberOfNodes();
148 wrapper.unmount();
149 expect(result).toBeFalsy();
150 const numberOfNodesAfterUnmounting = ReanimatedModule.getNumberOfNodes();
151 const pass =
152 numberOfNodesAfterUnmounting === 0 && numberOfNodesBeforeUnmounting > 0;
153 expect(pass).toBeTruthy();
154 });
155
156 it('fails if animation related nodes are detached if there are two children and only one detach', () => {
157 const { timing, Value } = Animated;
158 const transX = new Value(0);
159 const wrapper1 = renderer.create(
160 <Animated.View
161 style={{
162 transform: [{ translateX: transX }],
163 }}
164 />
165 );
166 const wrapper2 = renderer.create(
167 <Animated.View
168 style={{
169 transform: [{ translateX: transX }],
170 }}
171 />
172 );
173 const config = {
174 duration: 5000,
175 toValue: -120,
176 easing: Easing.inOut(Easing.ease),
177 };
178 const anim = timing(transX, config);
179 anim.start();
180 const numberOfNodesBeforeDetach = ReanimatedModule.getNumberOfNodes();
181 wrapper1.unmount();
182 const numberOfNodesAfterDetach = ReanimatedModule.getNumberOfNodes();
183 const result =
184 // 3 means AnimatedProps, AnimatedStyle and AnimatedTransform
185 // which are nodes not related to animation and has to be detached
186 numberOfNodesBeforeDetach - 3 === numberOfNodesAfterDetach &&
187 numberOfNodesAfterDetach > 3;
188 expect(result).toBeTruthy();
189 wrapper2.unmount();
190 expect(ReanimatedModule.getNumberOfNodes() === 0).toBeTruthy();
191 });
192
193 it('fails if animation attaches some node without view related', () => {
194 const { timing, Value } = Animated;
195 const transX = new Value(0);
196
197 const config = {
198 duration: 5000,
199 toValue: -120,
200 easing: Easing.inOut(Easing.ease),
201 };
202 const anim = timing(transX, config);
203 anim.start();
204 expect(ReanimatedModule.getNumberOfNodes()).toBe(0);
205 });
206});