下面列出了com.facebook.react.bridge.JavaOnlyArray#of ( ) 实例代码,或者点击链接到github查看源代码,也可以在右侧发表评论。
@Test
public void testNodeValueListenerIfNotListening() {
int nodeId = 1;
createSimpleAnimatedViewWithOpacity(1000, 0d);
JavaOnlyArray frames = JavaOnlyArray.of(0d, 0.2d, 0.4d, 0.6d, 0.8d, 1d);
Callback animationCallback = mock(Callback.class);
AnimatedNodeValueListener valueListener = mock(AnimatedNodeValueListener.class);
mNativeAnimatedNodesManager.startListeningToAnimatedNodeValue(nodeId, valueListener);
mNativeAnimatedNodesManager.startAnimatingNode(
1,
nodeId,
JavaOnlyMap.of("type", "frames", "frames", frames, "toValue", 1d),
animationCallback);
mNativeAnimatedNodesManager.runUpdates(nextFrameTime());
verify(valueListener).onValueUpdate(eq(0d));
mNativeAnimatedNodesManager.stopListeningToAnimatedNodeValue(nodeId);
reset(valueListener);
mNativeAnimatedNodesManager.runUpdates(nextFrameTime());
verifyNoMoreInteractions(valueListener);
}
@Test
public void testFramesAnimation() {
createSimpleAnimatedViewWithOpacity(1000, 0d);
JavaOnlyArray frames = JavaOnlyArray.of(0d, 0.2d, 0.4d, 0.6d, 0.8d, 1d);
Callback animationCallback = mock(Callback.class);
mNativeAnimatedNodesManager.startAnimatingNode(
1,
1,
JavaOnlyMap.of("type", "frames", "frames", frames, "toValue", 1d),
animationCallback);
ArgumentCaptor<ReactStylesDiffMap> stylesCaptor =
ArgumentCaptor.forClass(ReactStylesDiffMap.class);
for (int i = 0; i < frames.size(); i++) {
reset(mUIImplementationMock);
mNativeAnimatedNodesManager.runUpdates(nextFrameTime());
verify(mUIImplementationMock)
.synchronouslyUpdateViewOnUIThread(eq(1000), stylesCaptor.capture());
assertThat(stylesCaptor.getValue().getDouble("opacity", Double.NaN))
.isEqualTo(frames.getDouble(i));
}
reset(mUIImplementationMock);
mNativeAnimatedNodesManager.runUpdates(nextFrameTime());
verifyNoMoreInteractions(mUIImplementationMock);
}
@Test
public void testFramesAnimationLoopsFiveTimes() {
createSimpleAnimatedViewWithOpacity(1000, 0d);
JavaOnlyArray frames = JavaOnlyArray.of(0d, 0.2d, 0.4d, 0.6d, 0.8d, 1d);
Callback animationCallback = mock(Callback.class);
mNativeAnimatedNodesManager.startAnimatingNode(
1,
1,
JavaOnlyMap.of("type", "frames", "frames", frames, "toValue", 1d, "iterations", 5),
animationCallback);
ArgumentCaptor<ReactStylesDiffMap> stylesCaptor =
ArgumentCaptor.forClass(ReactStylesDiffMap.class);
for (int iteration = 0; iteration < 5; iteration++) {
for (int i = 0; i < frames.size(); i++) {
reset(mUIImplementationMock);
mNativeAnimatedNodesManager.runUpdates(nextFrameTime());
verify(mUIImplementationMock)
.synchronouslyUpdateViewOnUIThread(eq(1000), stylesCaptor.capture());
assertThat(stylesCaptor.getValue().getDouble("opacity", Double.NaN))
.isEqualTo(frames.getDouble(i));
}
}
reset(mUIImplementationMock);
mNativeAnimatedNodesManager.runUpdates(nextFrameTime());
verifyNoMoreInteractions(mUIImplementationMock);
}
@Test
public void testNodeValueListenerIfListening() {
int nodeId = 1;
createSimpleAnimatedViewWithOpacity(1000, 0d);
JavaOnlyArray frames = JavaOnlyArray.of(0d, 0.2d, 0.4d, 0.6d, 0.8d, 1d);
Callback animationCallback = mock(Callback.class);
AnimatedNodeValueListener valueListener = mock(AnimatedNodeValueListener.class);
mNativeAnimatedNodesManager.startListeningToAnimatedNodeValue(nodeId, valueListener);
mNativeAnimatedNodesManager.startAnimatingNode(
1,
nodeId,
JavaOnlyMap.of("type", "frames", "frames", frames, "toValue", 1d),
animationCallback);
for (int i = 0; i < frames.size(); i++) {
reset(valueListener);
mNativeAnimatedNodesManager.runUpdates(nextFrameTime());
verify(valueListener).onValueUpdate(eq(frames.getDouble(i)));
}
reset(valueListener);
mNativeAnimatedNodesManager.runUpdates(nextFrameTime());
verifyNoMoreInteractions(valueListener);
}
@Test
public void testAnimationCallbackFinish() {
createSimpleAnimatedViewWithOpacity(1000, 0d);
JavaOnlyArray frames = JavaOnlyArray.of(0d, 1d);
Callback animationCallback = mock(Callback.class);
mNativeAnimatedNodesManager.startAnimatingNode(
1,
1,
JavaOnlyMap.of("type", "frames", "frames", frames, "toValue", 1d),
animationCallback);
ArgumentCaptor<ReadableMap> callbackResponseCaptor = ArgumentCaptor.forClass(ReadableMap.class);
reset(animationCallback);
mNativeAnimatedNodesManager.runUpdates(nextFrameTime());
verifyNoMoreInteractions(animationCallback);
reset(animationCallback);
mNativeAnimatedNodesManager.runUpdates(nextFrameTime());
verify(animationCallback).invoke(callbackResponseCaptor.capture());
assertThat(callbackResponseCaptor.getValue().hasKey("finished")).isTrue();
assertThat(callbackResponseCaptor.getValue().getBoolean("finished")).isTrue();
reset(animationCallback);
mNativeAnimatedNodesManager.runUpdates(nextFrameTime());
verifyNoMoreInteractions(animationCallback);
}
@Test
public void testAdditionNode() {
createAnimatedGraphWithAdditionNode(50, 100d, 1000d);
Callback animationCallback = mock(Callback.class);
JavaOnlyArray frames = JavaOnlyArray.of(0d, 1d);
mNativeAnimatedNodesManager.startAnimatingNode(
1,
1,
JavaOnlyMap.of("type", "frames", "frames", frames, "toValue", 101d),
animationCallback);
mNativeAnimatedNodesManager.startAnimatingNode(
2,
2,
JavaOnlyMap.of("type", "frames", "frames", frames, "toValue", 1010d),
animationCallback);
ArgumentCaptor<ReactStylesDiffMap> stylesCaptor =
ArgumentCaptor.forClass(ReactStylesDiffMap.class);
reset(mUIImplementationMock);
mNativeAnimatedNodesManager.runUpdates(nextFrameTime());
verify(mUIImplementationMock).synchronouslyUpdateViewOnUIThread(eq(50), stylesCaptor.capture());
assertThat(stylesCaptor.getValue().getDouble("translateX", Double.NaN)).isEqualTo(1100d);
reset(mUIImplementationMock);
mNativeAnimatedNodesManager.runUpdates(nextFrameTime());
verify(mUIImplementationMock)
.synchronouslyUpdateViewOnUIThread(eq(50), stylesCaptor.capture());
assertThat(stylesCaptor.getValue().getDouble("translateX", Double.NaN)).isEqualTo(1111d);
reset(mUIImplementationMock);
mNativeAnimatedNodesManager.runUpdates(nextFrameTime());
verifyNoMoreInteractions(mUIImplementationMock);
}
/**
* Verifies that {@link NativeAnimatedNodesManager#runUpdates} updates the view correctly in case
* when one of the addition input nodes has started animating while the other one has not.
*
* We expect that the output of the addition node will take the starting value of the second input
* node even though the node hasn't been connected to an active animation driver.
*/
@Test
public void testViewReceiveUpdatesIfOneOfAnimationHasntStarted() {
createAnimatedGraphWithAdditionNode(50, 100d, 1000d);
// Start animating only the first addition input node
Callback animationCallback = mock(Callback.class);
JavaOnlyArray frames = JavaOnlyArray.of(0d, 1d);
mNativeAnimatedNodesManager.startAnimatingNode(
1,
1,
JavaOnlyMap.of("type", "frames", "frames", frames, "toValue", 101d),
animationCallback);
ArgumentCaptor<ReactStylesDiffMap> stylesCaptor =
ArgumentCaptor.forClass(ReactStylesDiffMap.class);
reset(mUIImplementationMock);
mNativeAnimatedNodesManager.runUpdates(nextFrameTime());
verify(mUIImplementationMock).synchronouslyUpdateViewOnUIThread(eq(50), stylesCaptor.capture());
assertThat(stylesCaptor.getValue().getDouble("translateX", Double.NaN)).isEqualTo(1100d);
reset(mUIImplementationMock);
mNativeAnimatedNodesManager.runUpdates(nextFrameTime());
verify(mUIImplementationMock)
.synchronouslyUpdateViewOnUIThread(eq(50), stylesCaptor.capture());
assertThat(stylesCaptor.getValue().getDouble("translateX", Double.NaN)).isEqualTo(1101d);
reset(mUIImplementationMock);
mNativeAnimatedNodesManager.runUpdates(nextFrameTime());
verifyNoMoreInteractions(mUIImplementationMock);
}
/**
* Verifies that {@link NativeAnimatedNodesManager#runUpdates} updates the view correctly in case
* when one of the addition input nodes animation finishes before the other.
*
* We expect that the output of the addition node after one of the animation has finished will
* take the last value of the animated node and the view will receive updates up until the second
* animation is over.
*/
@Test
public void testViewReceiveUpdatesWhenOneOfAnimationHasFinished() {
createAnimatedGraphWithAdditionNode(50, 100d, 1000d);
Callback animationCallback = mock(Callback.class);
// Start animating for the first addition input node, will have 2 frames only
JavaOnlyArray firstFrames = JavaOnlyArray.of(0d, 1d);
mNativeAnimatedNodesManager.startAnimatingNode(
1,
1,
JavaOnlyMap.of("type", "frames", "frames", firstFrames, "toValue", 200d),
animationCallback);
// Start animating for the first addition input node, will have 6 frames
JavaOnlyArray secondFrames = JavaOnlyArray.of(0d, 0.2d, 0.4d, 0.6d, 0.8d, 1d);
mNativeAnimatedNodesManager.startAnimatingNode(
2,
2,
JavaOnlyMap.of("type", "frames", "frames", secondFrames, "toValue", 1010d),
animationCallback);
ArgumentCaptor<ReactStylesDiffMap> stylesCaptor =
ArgumentCaptor.forClass(ReactStylesDiffMap.class);
reset(mUIImplementationMock);
mNativeAnimatedNodesManager.runUpdates(nextFrameTime());
verify(mUIImplementationMock).synchronouslyUpdateViewOnUIThread(eq(50), stylesCaptor.capture());
assertThat(stylesCaptor.getValue().getDouble("translateX", Double.NaN)).isEqualTo(1100d);
for (int i = 1; i < secondFrames.size(); i++) {
reset(mUIImplementationMock);
mNativeAnimatedNodesManager.runUpdates(nextFrameTime());
verify(mUIImplementationMock)
.synchronouslyUpdateViewOnUIThread(eq(50), stylesCaptor.capture());
assertThat(stylesCaptor.getValue().getDouble("translateX", Double.NaN))
.isEqualTo(1200d + secondFrames.getDouble(i) * 10d);
}
reset(mUIImplementationMock);
mNativeAnimatedNodesManager.runUpdates(nextFrameTime());
verifyNoMoreInteractions(mUIImplementationMock);
}
@Test
public void testMultiplicationNode() {
mNativeAnimatedNodesManager.createAnimatedNode(
1,
JavaOnlyMap.of("type", "value", "value", 1d, "offset", 0d));
mNativeAnimatedNodesManager.createAnimatedNode(
2,
JavaOnlyMap.of("type", "value", "value", 5d, "offset", 0d));
mNativeAnimatedNodesManager.createAnimatedNode(
3,
JavaOnlyMap.of("type", "multiplication", "input", JavaOnlyArray.of(1, 2)));
mNativeAnimatedNodesManager.createAnimatedNode(
4,
JavaOnlyMap.of("type", "style", "style", JavaOnlyMap.of("translateX", 3)));
mNativeAnimatedNodesManager.createAnimatedNode(
5,
JavaOnlyMap.of("type", "props", "props", JavaOnlyMap.of("style", 4)));
mNativeAnimatedNodesManager.connectAnimatedNodes(1, 3);
mNativeAnimatedNodesManager.connectAnimatedNodes(2, 3);
mNativeAnimatedNodesManager.connectAnimatedNodes(3, 4);
mNativeAnimatedNodesManager.connectAnimatedNodes(4, 5);
mNativeAnimatedNodesManager.connectAnimatedNodeToView(5, 50);
Callback animationCallback = mock(Callback.class);
JavaOnlyArray frames = JavaOnlyArray.of(0d, 1d);
mNativeAnimatedNodesManager.startAnimatingNode(
1,
1,
JavaOnlyMap.of("type", "frames", "frames", frames, "toValue", 2d),
animationCallback);
mNativeAnimatedNodesManager.startAnimatingNode(
2,
2,
JavaOnlyMap.of("type", "frames", "frames", frames, "toValue", 10d),
animationCallback);
ArgumentCaptor<ReactStylesDiffMap> stylesCaptor =
ArgumentCaptor.forClass(ReactStylesDiffMap.class);
reset(mUIImplementationMock);
mNativeAnimatedNodesManager.runUpdates(nextFrameTime());
verify(mUIImplementationMock).synchronouslyUpdateViewOnUIThread(eq(50), stylesCaptor.capture());
assertThat(stylesCaptor.getValue().getDouble("translateX", Double.NaN)).isEqualTo(5d);
reset(mUIImplementationMock);
mNativeAnimatedNodesManager.runUpdates(nextFrameTime());
verify(mUIImplementationMock).synchronouslyUpdateViewOnUIThread(eq(50), stylesCaptor.capture());
assertThat(stylesCaptor.getValue().getDouble("translateX", Double.NaN)).isEqualTo(20d);
reset(mUIImplementationMock);
mNativeAnimatedNodesManager.runUpdates(nextFrameTime());
verifyNoMoreInteractions(mUIImplementationMock);
}
/**
* This test verifies that when {@link NativeAnimatedModule#stopAnimation} is called the animation
* will no longer be updating the nodes it has been previously attached to and that the animation
* callback will be triggered with {@code {finished: false}}
*/
@Test
public void testHandleStoppingAnimation() {
createSimpleAnimatedViewWithOpacity(1000, 0d);
JavaOnlyArray frames = JavaOnlyArray.of(0d, 0.2d, 0.4d, 0.6d, 0.8d, 1.0d);
Callback animationCallback = mock(Callback.class);
mNativeAnimatedNodesManager.startAnimatingNode(
404,
1,
JavaOnlyMap.of("type", "frames", "frames", frames, "toValue", 1d),
animationCallback);
ArgumentCaptor<ReadableMap> callbackResponseCaptor = ArgumentCaptor.forClass(ReadableMap.class);
reset(animationCallback);
reset(mUIImplementationMock);
mNativeAnimatedNodesManager.runUpdates(nextFrameTime());
mNativeAnimatedNodesManager.runUpdates(nextFrameTime());
verify(mUIImplementationMock, times(2))
.synchronouslyUpdateViewOnUIThread(anyInt(), any(ReactStylesDiffMap.class));
verifyNoMoreInteractions(animationCallback);
reset(animationCallback);
reset(mUIImplementationMock);
mNativeAnimatedNodesManager.stopAnimation(404);
verify(animationCallback).invoke(callbackResponseCaptor.capture());
verifyNoMoreInteractions(animationCallback);
verifyNoMoreInteractions(mUIImplementationMock);
assertThat(callbackResponseCaptor.getValue().hasKey("finished")).isTrue();
assertThat(callbackResponseCaptor.getValue().getBoolean("finished")).isFalse();
reset(animationCallback);
reset(mUIImplementationMock);
// Run "update" loop a few more times -> we expect no further updates nor callback calls to be
// triggered
for (int i = 0; i < 5; i++) {
mNativeAnimatedNodesManager.runUpdates(nextFrameTime());
}
verifyNoMoreInteractions(mUIImplementationMock);
verifyNoMoreInteractions(animationCallback);
}
@Test
public void testInterpolationNode() {
mNativeAnimatedNodesManager.createAnimatedNode(
1,
JavaOnlyMap.of("type", "value", "value", 10d, "offset", 0d));
mNativeAnimatedNodesManager.createAnimatedNode(
2,
JavaOnlyMap.of(
"type",
"interpolation",
"inputRange",
JavaOnlyArray.of(10d, 20d),
"outputRange",
JavaOnlyArray.of(0d, 1d),
"extrapolateLeft",
"extend",
"extrapolateRight",
"extend"));
mNativeAnimatedNodesManager.createAnimatedNode(
3,
JavaOnlyMap.of("type", "style", "style", JavaOnlyMap.of("opacity", 2)));
mNativeAnimatedNodesManager.createAnimatedNode(
4,
JavaOnlyMap.of("type", "props", "props", JavaOnlyMap.of("style", 3)));
mNativeAnimatedNodesManager.connectAnimatedNodes(1, 2);
mNativeAnimatedNodesManager.connectAnimatedNodes(2, 3);
mNativeAnimatedNodesManager.connectAnimatedNodes(3, 4);
mNativeAnimatedNodesManager.connectAnimatedNodeToView(4, 50);
Callback animationCallback = mock(Callback.class);
JavaOnlyArray frames = JavaOnlyArray.of(0d, 0.2d, 0.4d, 0.6d, 0.8d, 1d);
mNativeAnimatedNodesManager.startAnimatingNode(
1,
1,
JavaOnlyMap.of("type", "frames", "frames", frames, "toValue", 20d),
animationCallback);
ArgumentCaptor<ReactStylesDiffMap> stylesCaptor =
ArgumentCaptor.forClass(ReactStylesDiffMap.class);
for (int i = 0; i < frames.size(); i++) {
reset(mUIImplementationMock);
mNativeAnimatedNodesManager.runUpdates(nextFrameTime());
verify(mUIImplementationMock)
.synchronouslyUpdateViewOnUIThread(eq(50), stylesCaptor.capture());
assertThat(stylesCaptor.getValue().getDouble("opacity", Double.NaN))
.isEqualTo(frames.getDouble(i));
}
reset(mUIImplementationMock);
mNativeAnimatedNodesManager.runUpdates(nextFrameTime());
verifyNoMoreInteractions(mUIImplementationMock);
}
@Test
public void testRestoreDefaultProps() {
int viewTag = 1000;
int propsNodeTag = 3;
mNativeAnimatedNodesManager.createAnimatedNode(
1,
JavaOnlyMap.of("type", "value", "value", 1d, "offset", 0d));
mNativeAnimatedNodesManager.createAnimatedNode(
2,
JavaOnlyMap.of("type", "style", "style", JavaOnlyMap.of("opacity", 1)));
mNativeAnimatedNodesManager.createAnimatedNode(
propsNodeTag,
JavaOnlyMap.of("type", "props", "props", JavaOnlyMap.of("style", 2)));
mNativeAnimatedNodesManager.connectAnimatedNodes(1, 2);
mNativeAnimatedNodesManager.connectAnimatedNodes(2, propsNodeTag);
mNativeAnimatedNodesManager.connectAnimatedNodeToView(propsNodeTag, viewTag);
JavaOnlyArray frames = JavaOnlyArray.of(0d, 0.5d, 1d);
Callback animationCallback = mock(Callback.class);
mNativeAnimatedNodesManager.startAnimatingNode(
1,
1,
JavaOnlyMap.of("type", "frames", "frames", frames, "toValue", 0d),
animationCallback);
ArgumentCaptor<ReactStylesDiffMap> stylesCaptor =
ArgumentCaptor.forClass(ReactStylesDiffMap.class);
for (int i = 0; i < frames.size(); i++) {
reset(mUIImplementationMock);
mNativeAnimatedNodesManager.runUpdates(nextFrameTime());
}
verify(mUIImplementationMock).synchronouslyUpdateViewOnUIThread(eq(viewTag), stylesCaptor.capture());
assertThat(stylesCaptor.getValue().getDouble("opacity", Double.NaN)).isEqualTo(0);
reset(mUIImplementationMock);
mNativeAnimatedNodesManager.restoreDefaultValues(propsNodeTag, viewTag);
verify(mUIImplementationMock).synchronouslyUpdateViewOnUIThread(eq(viewTag), stylesCaptor.capture());
assertThat(stylesCaptor.getValue().isNull("opacity"));
}
/**
* In this test we verify that when value is being tracked we can update destination value in the
* middle of ongoing animation and the animation will update and animate to the new spot. This is
* tested using simple 5 frame backed timing animation.
*/
@Test
public void testTracking() {
JavaOnlyArray frames = JavaOnlyArray.of(0d, 0.25d, 0.5d, 0.75d, 1d);
JavaOnlyMap animationConfig = JavaOnlyMap.of("type", "frames", "frames", frames);
createAnimatedGraphWithTrackingNode(1000, 0d, animationConfig);
ArgumentCaptor<ReactStylesDiffMap> stylesCaptor =
ArgumentCaptor.forClass(ReactStylesDiffMap.class);
reset(mUIImplementationMock);
mNativeAnimatedNodesManager.runUpdates(nextFrameTime());
verify(mUIImplementationMock).synchronouslyUpdateViewOnUIThread(eq(1000), stylesCaptor.capture());
assertThat(stylesCaptor.getValue().getDouble("translateX", Double.NaN)).isEqualTo(0d);
// update "toValue" to 100, we expect tracking animation to animate now from 0 to 100 in 5 steps
mNativeAnimatedNodesManager.setAnimatedNodeValue(1, 100d);
mNativeAnimatedNodesManager.runUpdates(nextFrameTime()); // kick off the animation
for (int i = 0; i < frames.size(); i++) {
reset(mUIImplementationMock);
mNativeAnimatedNodesManager.runUpdates(nextFrameTime());
verify(mUIImplementationMock)
.synchronouslyUpdateViewOnUIThread(eq(1000), stylesCaptor.capture());
assertThat(stylesCaptor.getValue().getDouble("translateX", Double.NaN))
.isEqualTo(frames.getDouble(i) * 100d);
}
// update "toValue" to 0 but run only two frames from the animation,
// we expect tracking animation to animate now from 100 to 75
mNativeAnimatedNodesManager.setAnimatedNodeValue(1, 0d);
mNativeAnimatedNodesManager.runUpdates(nextFrameTime()); // kick off the animation
for (int i = 0; i < 2; i++) {
reset(mUIImplementationMock);
mNativeAnimatedNodesManager.runUpdates(nextFrameTime());
verify(mUIImplementationMock)
.synchronouslyUpdateViewOnUIThread(eq(1000), stylesCaptor.capture());
assertThat(stylesCaptor.getValue().getDouble("translateX", Double.NaN))
.isEqualTo(100d * (1d - frames.getDouble(i)));
}
// at this point we expect tracking value to be at 75
assertThat(((ValueAnimatedNode) mNativeAnimatedNodesManager.getNodeById(3)).getValue())
.isEqualTo(75d);
// we update "toValue" again to 100 and expect the animation to restart from the current place
mNativeAnimatedNodesManager.setAnimatedNodeValue(1, 100d);
mNativeAnimatedNodesManager.runUpdates(nextFrameTime()); // kick off the animation
for (int i = 0; i < frames.size(); i++) {
reset(mUIImplementationMock);
mNativeAnimatedNodesManager.runUpdates(nextFrameTime());
verify(mUIImplementationMock)
.synchronouslyUpdateViewOnUIThread(eq(1000), stylesCaptor.capture());
assertThat(stylesCaptor.getValue().getDouble("translateX", Double.NaN))
.isEqualTo(50d + 50d * frames.getDouble(i));
}
}
/**
* In this test we verify that when tracking is set up for a given animated node and when the
* animation settles it will not be registered as an active animation and therefore will not
* consume resources on running the animation that has already completed. Then we verify that when
* the value updates the animation will resume as expected and the complete again when reaches the
* end.
*/
@Test
public void testTrackingPausesWhenEndValueIsReached() {
JavaOnlyArray frames = JavaOnlyArray.of(0d, 0.5d, 1d);
JavaOnlyMap animationConfig = JavaOnlyMap.of("type", "frames", "frames", frames);
createAnimatedGraphWithTrackingNode(1000, 0d, animationConfig);
mNativeAnimatedNodesManager.setAnimatedNodeValue(1, 100d);
mNativeAnimatedNodesManager.runUpdates(nextFrameTime()); // make sure animation starts
reset(mUIImplementationMock);
for (int i = 0; i < frames.size(); i++) {
assertThat(mNativeAnimatedNodesManager.hasActiveAnimations()).isTrue();
mNativeAnimatedNodesManager.runUpdates(nextFrameTime());
}
verify(mUIImplementationMock, times(frames.size()))
.synchronouslyUpdateViewOnUIThread(eq(1000), any(ReactStylesDiffMap.class));
// the animation has completed, we expect no updates to be done
reset(mUIImplementationMock);
assertThat(mNativeAnimatedNodesManager.hasActiveAnimations()).isFalse();
mNativeAnimatedNodesManager.runUpdates(nextFrameTime());
verifyNoMoreInteractions(mUIImplementationMock);
// we update end value and expect the animation to restart
mNativeAnimatedNodesManager.setAnimatedNodeValue(1, 200d);
mNativeAnimatedNodesManager.runUpdates(nextFrameTime()); // make sure animation starts
reset(mUIImplementationMock);
for (int i = 0; i < frames.size(); i++) {
assertThat(mNativeAnimatedNodesManager.hasActiveAnimations()).isTrue();
mNativeAnimatedNodesManager.runUpdates(nextFrameTime());
}
verify(mUIImplementationMock, times(frames.size()))
.synchronouslyUpdateViewOnUIThread(eq(1000), any(ReactStylesDiffMap.class));
// the animation has completed, we expect no updates to be done
reset(mUIImplementationMock);
assertThat(mNativeAnimatedNodesManager.hasActiveAnimations()).isFalse();
mNativeAnimatedNodesManager.runUpdates(nextFrameTime());
verifyNoMoreInteractions(mUIImplementationMock);
}