Update NativeAnimatedNodeTraversalTest to be more idiomatic (#37970)

Summary:
Follow up to:
- https://github.com/facebook/react-native/pull/37960

## Changelog:

[INTERNAL] - Update NativeAnimatedNodeTraversalTest to be more idiomatic

Pull Request resolved: https://github.com/facebook/react-native/pull/37970

Test Plan: Will run on CI

Reviewed By: javache, cipolleschi

Differential Revision: D46853581

Pulled By: cortinico

fbshipit-source-id: 73776493163413b045482344b7b1be0635f5aa25
This commit is contained in:
Nicola Corti
2023-06-23 02:31:39 -07:00
committed by Facebook GitHub Bot
parent 7e934947d7
commit c54092fe3b
@@ -7,6 +7,7 @@
package com.facebook.react.animated
import android.annotation.SuppressLint
import com.facebook.react.bridge.Arguments
import com.facebook.react.bridge.Callback
import com.facebook.react.bridge.CatalystInstance
@@ -21,6 +22,7 @@ import com.facebook.react.uimanager.events.Event
import com.facebook.react.uimanager.events.EventDispatcher
import com.facebook.react.uimanager.events.RCTEventEmitter
import kotlin.collections.Map
import kotlin.math.abs
import org.assertj.core.api.Assertions.assertThat
import org.junit.Before
import org.junit.Rule
@@ -50,11 +52,6 @@ import org.robolectric.RobolectricTestRunner
class NativeAnimatedNodeTraversalTest {
@get:Rule var rule = PowerMockRule()
companion object {
private val FRAME_LEN_NANOS: Long = 1000000000L / 60L
private val INITIAL_FRAME_TIME_NANOS: Long = 14599233201256L /* random */
}
private var frameTimeNanos: Long = 0L
private lateinit var reactApplicationContextMock: ReactApplicationContext
private lateinit var catalystInstanceMock: CatalystInstance
@@ -78,7 +75,7 @@ class NativeAnimatedNodeTraversalTest {
reactApplicationContextMock = mock(ReactApplicationContext::class.java)
whenever(reactApplicationContextMock.hasActiveReactInstance()).thenAnswer { true }
whenever(reactApplicationContextMock.hasCatalystInstance()).thenAnswer { true }
whenever(reactApplicationContextMock.getCatalystInstance()).thenAnswer { catalystInstanceMock }
whenever(reactApplicationContextMock.catalystInstance).thenAnswer { catalystInstanceMock }
whenever(reactApplicationContextMock.getNativeModule(UIManagerModule::class.java)).thenAnswer {
uiManagerMock
}
@@ -93,21 +90,19 @@ class NativeAnimatedNodeTraversalTest {
uiManagerMock = mock(UIManagerModule::class.java)
eventDispatcherMock = mock(EventDispatcher::class.java)
whenever(uiManagerMock.getEventDispatcher()).thenAnswer { eventDispatcherMock }
whenever(uiManagerMock.getConstants()).thenAnswer {
whenever(uiManagerMock.eventDispatcher).thenAnswer { eventDispatcherMock }
whenever(uiManagerMock.constants).thenAnswer {
MapBuilder.of("customDirectEventTypes", MapBuilder.newHashMap<Any, Any>())
}
whenever(uiManagerMock.getDirectEventNamesResolver()).thenAnswer {
whenever(uiManagerMock.directEventNamesResolver).thenAnswer {
object : UIManagerModule.CustomEventNamesResolver {
override fun resolveCustomEventName(eventName: String): String {
val directEventTypes: Map<String, Map<String, String>>? =
uiManagerMock?.constants?.get("customDirectEventTypes")
as? Map<String, Map<String, String>>?
if (directEventTypes != null) {
val customEventType: Map<String, String>? =
directEventTypes[eventName] as? Map<String, String>?
if (customEventType != null) {
return customEventType["registrationName"] ?: eventName
val constants: Map<String, Any?> = uiManagerMock.constants ?: emptyMap()
val directEventTypes: Any? = constants["customDirectEventTypes"]
if (directEventTypes != null && directEventTypes is Map<*, *>) {
val customEventType = directEventTypes[eventName]
if (customEventType != null && customEventType is Map<*, *>) {
return customEventType["registrationName"] as? String ?: eventName
}
}
return eventName
@@ -129,7 +124,8 @@ class NativeAnimatedNodeTraversalTest {
* <p>Nodes are connected as follows (nodes IDs in parens): ValueNode(1) -> StyleNode(2) ->
* PropNode(3)
*/
private fun createSimpleAnimatedViewWithOpacity(viewTag: Int, opacity: Double) {
private fun createSimpleAnimatedViewWithOpacity(viewTag: Int = 1000) {
val opacity = 0.0
nativeAnimatedNodesManager.createAnimatedNode(
1, JavaOnlyMap.of("type", "value", "value", opacity, "offset", 0.0))
nativeAnimatedNodesManager.createAnimatedNode(
@@ -143,7 +139,7 @@ class NativeAnimatedNodeTraversalTest {
@Test
fun testFramesAnimation() {
createSimpleAnimatedViewWithOpacity(1000, 0.0)
createSimpleAnimatedViewWithOpacity()
val frames: JavaOnlyArray = JavaOnlyArray.of(0.0, 0.2, 0.4, 0.6, 0.8, 1.0)
@@ -157,7 +153,7 @@ class NativeAnimatedNodeTraversalTest {
reset(uiManagerMock)
nativeAnimatedNodesManager.runUpdates(nextFrameTime())
verify(uiManagerMock).synchronouslyUpdateViewOnUIThread(eq(1000), stylesCaptor.capture())
assertThat(stylesCaptor.getValue().getDouble("opacity")).isEqualTo(frames.getDouble(i))
assertThat(stylesCaptor.value.getDouble("opacity")).isEqualTo(frames.getDouble(i))
}
reset(uiManagerMock)
@@ -167,7 +163,7 @@ class NativeAnimatedNodeTraversalTest {
@Test
fun testFramesAnimationLoopsFiveTimes() {
createSimpleAnimatedViewWithOpacity(1000, 0.0)
createSimpleAnimatedViewWithOpacity()
val frames: JavaOnlyArray = JavaOnlyArray.of(0.0, 0.2, 0.4, 0.6, 0.8, 1.0)
val animationCallback: Callback = mock(Callback::class.java)
@@ -184,7 +180,7 @@ class NativeAnimatedNodeTraversalTest {
reset(uiManagerMock)
nativeAnimatedNodesManager.runUpdates(nextFrameTime())
verify(uiManagerMock).synchronouslyUpdateViewOnUIThread(eq(1000), stylesCaptor.capture())
assertThat(stylesCaptor.getValue().getDouble("opacity")).isEqualTo(frames.getDouble(i))
assertThat(stylesCaptor.value.getDouble("opacity")).isEqualTo(frames.getDouble(i))
}
}
@@ -197,7 +193,7 @@ class NativeAnimatedNodeTraversalTest {
fun testNodeValueListenerIfNotListening() {
val nodeId: Int = 1
createSimpleAnimatedViewWithOpacity(1000, 0.0)
createSimpleAnimatedViewWithOpacity()
val frames: JavaOnlyArray = JavaOnlyArray.of(0.0, 0.2, 0.4, 0.6, 0.8, 1.0)
val animationCallback: Callback = mock(Callback::class.java)
@@ -224,7 +220,7 @@ class NativeAnimatedNodeTraversalTest {
fun testNodeValueListenerIfListening() {
val nodeId: Int = 1
createSimpleAnimatedViewWithOpacity(1000, 0.0)
createSimpleAnimatedViewWithOpacity()
val frames: JavaOnlyArray = JavaOnlyArray.of(0.0, 0.2, 0.4, 0.6, 0.8, 1.0)
val animationCallback: Callback = mock(Callback::class.java)
@@ -248,8 +244,11 @@ class NativeAnimatedNodeTraversalTest {
verifyNoMoreInteractions(valueListener)
}
fun performSpringAnimationTestWithConfig(config: JavaOnlyMap?, testForCriticallyDamped: Boolean) {
createSimpleAnimatedViewWithOpacity(1000, 0.0)
private fun performSpringAnimationTestWithConfig(
config: JavaOnlyMap?,
testForCriticallyDamped: Boolean
) {
createSimpleAnimatedViewWithOpacity()
val animationCallback: Callback = mock(Callback::class.java)
@@ -260,7 +259,7 @@ class NativeAnimatedNodeTraversalTest {
reset(uiManagerMock)
nativeAnimatedNodesManager.runUpdates(nextFrameTime())
verify(uiManagerMock).synchronouslyUpdateViewOnUIThread(eq(1000), stylesCaptor.capture())
assertThat(stylesCaptor.getValue().getDouble("opacity")).isEqualTo(0.0)
assertThat(stylesCaptor.value.getDouble("opacity")).isEqualTo(0.0)
var previousValue: Double = 0.0
var wasGreaterThanOne: Boolean = false
@@ -271,12 +270,12 @@ class NativeAnimatedNodeTraversalTest {
nativeAnimatedNodesManager.runUpdates(nextFrameTime())
verify(uiManagerMock, atMost(1))
.synchronouslyUpdateViewOnUIThread(eq(1000), stylesCaptor.capture())
val currentValue: Double = stylesCaptor.getValue().getDouble("opacity")
val currentValue: Double = stylesCaptor.value.getDouble("opacity")
if (currentValue > 1.0) {
wasGreaterThanOne = true
}
// verify that animation step is relatively small
assertThat(java.lang.Math.abs(currentValue - previousValue)).isLessThan(0.12)
assertThat(abs(currentValue - previousValue)).isLessThan(0.12)
previousValue = currentValue
}
// verify that we've reach the final value at the end of animation
@@ -284,9 +283,9 @@ class NativeAnimatedNodeTraversalTest {
// verify that value has reached some maximum value that is greater than the final value
// (bounce)
if (testForCriticallyDamped) {
assertThat(!wasGreaterThanOne)
assertThat(!wasGreaterThanOne).isTrue
} else {
assertThat(wasGreaterThanOne)
assertThat(wasGreaterThanOne).isTrue
}
reset(uiManagerMock)
nativeAnimatedNodesManager.runUpdates(nextFrameTime())
@@ -345,7 +344,7 @@ class NativeAnimatedNodeTraversalTest {
@Test
fun testSpringAnimationLoopsFiveTimes() {
createSimpleAnimatedViewWithOpacity(1000, 0.0)
createSimpleAnimatedViewWithOpacity()
val animationCallback: Callback = mock(Callback::class.java)
nativeAnimatedNodesManager.startAnimatingNode(
@@ -379,7 +378,7 @@ class NativeAnimatedNodeTraversalTest {
reset(uiManagerMock)
nativeAnimatedNodesManager.runUpdates(nextFrameTime())
verify(uiManagerMock).synchronouslyUpdateViewOnUIThread(eq(1000), stylesCaptor.capture())
assertThat(stylesCaptor.getValue().getDouble("opacity")).isEqualTo(0.0)
assertThat(stylesCaptor.value.getDouble("opacity")).isEqualTo(0.0)
var previousValue: Double = 0.0
var wasGreaterThanOne: Boolean = false
@@ -391,31 +390,30 @@ class NativeAnimatedNodeTraversalTest {
nativeAnimatedNodesManager.runUpdates(nextFrameTime())
verify(uiManagerMock, atMost(1))
.synchronouslyUpdateViewOnUIThread(eq(1000), stylesCaptor.capture())
val currentValue: Double = stylesCaptor.getValue().getDouble("opacity")
val currentValue: Double = stylesCaptor.value.getDouble("opacity")
if (currentValue > 1.0) {
wasGreaterThanOne = true
}
// Test to see if it reset after coming to rest
if (didComeToRest &&
currentValue == 0.0 &&
Math.abs(Math.abs(currentValue - previousValue) - 1.0) < 0.001) {
abs(abs(currentValue - previousValue) - 1.0) < 0.001) {
numberOfResets++
}
// verify that an animation step is relatively small, unless it has come to rest and
// reset
if (!didComeToRest) assertThat(Math.abs(currentValue - previousValue)).isLessThan(0.12)
if (!didComeToRest) assertThat(abs(currentValue - previousValue)).isLessThan(0.12)
// record that the animation did come to rest when it rests on toValue
didComeToRest =
Math.abs(currentValue - 1.0) < 0.001 && Math.abs(currentValue - previousValue) < 0.001
didComeToRest = abs(currentValue - 1.0) < 0.001 && abs(currentValue - previousValue) < 0.001
previousValue = currentValue
}
// verify that we've reach the final value at the end of animation
assertThat(previousValue).isEqualTo(1.0)
// verify that value has reached some maximum value that is greater than the final value
// (bounce)
assertThat(wasGreaterThanOne)
assertThat(wasGreaterThanOne).isTrue
// verify that value reset 4 times after finishing a full animation
assertThat(numberOfResets).isEqualTo(4)
reset(uiManagerMock)
@@ -425,7 +423,7 @@ class NativeAnimatedNodeTraversalTest {
@Test
fun testDecayAnimation() {
createSimpleAnimatedViewWithOpacity(1000, 0.0)
createSimpleAnimatedViewWithOpacity()
val animationCallback: Callback = mock(Callback::class.java)
nativeAnimatedNodesManager.startAnimatingNode(
@@ -440,7 +438,7 @@ class NativeAnimatedNodeTraversalTest {
nativeAnimatedNodesManager.runUpdates(nextFrameTime())
verify(uiManagerMock, atMost(1))
.synchronouslyUpdateViewOnUIThread(eq(1000), stylesCaptor.capture())
var previousValue: Double = stylesCaptor.getValue().getDouble("opacity")
var previousValue: Double = stylesCaptor.value.getDouble("opacity")
var previousDiff: Double = Double.POSITIVE_INFINITY
/* run 3 secs of animation */
for (i in 0 until 3 * 60) {
@@ -448,20 +446,20 @@ class NativeAnimatedNodeTraversalTest {
nativeAnimatedNodesManager.runUpdates(nextFrameTime())
verify(uiManagerMock, atMost(1))
.synchronouslyUpdateViewOnUIThread(eq(1000), stylesCaptor.capture())
val currentValue: Double = stylesCaptor.getValue().getDouble("opacity")
val currentValue: Double = stylesCaptor.value.getDouble("opacity")
val currentDiff: Double = currentValue - previousValue
// verify monotonicity
// greater *or equal* because the animation stops during these 3 seconds
assertThat(currentValue).`as`("on frame " + i).isGreaterThanOrEqualTo(previousValue)
assertThat(currentValue).describedAs("on frame $i").isGreaterThanOrEqualTo(previousValue)
// verify decay
if (i > 3) {
// i > 3 because that's how long it takes to settle previousDiff
if (i % 3 != 0) {
// i % 3 != 0 because every 3 frames we go a tiny
// bit faster, because frame length is 16.(6)ms
assertThat(currentDiff).`as`("on frame " + i).isLessThanOrEqualTo(previousDiff)
assertThat(currentDiff).describedAs("on frame $i").isLessThanOrEqualTo(previousDiff)
} else {
assertThat(currentDiff).`as`("on frame " + i).isGreaterThanOrEqualTo(previousDiff)
assertThat(currentDiff).describedAs("on frame $i").isGreaterThanOrEqualTo(previousDiff)
}
}
previousValue = currentValue
@@ -475,7 +473,7 @@ class NativeAnimatedNodeTraversalTest {
@Test
fun testDecayAnimationLoopsFiveTimes() {
createSimpleAnimatedViewWithOpacity(1000, 0.0)
createSimpleAnimatedViewWithOpacity()
val animationCallback: Callback = mock(Callback::class.java)
nativeAnimatedNodesManager.startAnimatingNode(
@@ -490,8 +488,8 @@ class NativeAnimatedNodeTraversalTest {
nativeAnimatedNodesManager.runUpdates(nextFrameTime())
verify(uiManagerMock, atMost(1))
.synchronouslyUpdateViewOnUIThread(eq(1000), stylesCaptor.capture())
var previousValue: Double = stylesCaptor.getValue().getDouble("opacity")
val initialValue: Double = stylesCaptor.getValue().getDouble("opacity")
var previousValue: Double = stylesCaptor.value.getDouble("opacity")
val initialValue: Double = stylesCaptor.value.getDouble("opacity")
var didComeToRest: Boolean = false
var numberOfResets: Int = 0
/* run 3 secs of animation, five times */
@@ -500,7 +498,7 @@ class NativeAnimatedNodeTraversalTest {
nativeAnimatedNodesManager.runUpdates(nextFrameTime())
verify(uiManagerMock, atMost(1))
.synchronouslyUpdateViewOnUIThread(eq(1000), stylesCaptor.capture())
val currentValue: Double = stylesCaptor.getValue().getDouble("opacity")
val currentValue: Double = stylesCaptor.value.getDouble("opacity")
val currentDiff: Double = currentValue - previousValue
// Test to see if it reset after coming to rest (i.e. dropped back to )
if (didComeToRest && currentValue == initialValue) {
@@ -510,11 +508,11 @@ class NativeAnimatedNodeTraversalTest {
// verify monotonicity, unless it has come to rest and reset
// greater *or equal* because the animation stops during these 3 seconds
if (!didComeToRest) {
assertThat(currentValue).`as`("on frame " + i).isGreaterThanOrEqualTo(previousValue)
assertThat(currentValue).describedAs("on frame $i").isGreaterThanOrEqualTo(previousValue)
}
// Test if animation has come to rest using the 0.1 threshold from DecayAnimation.java
didComeToRest = Math.abs(currentDiff) < 0.1
didComeToRest = abs(currentDiff) < 0.1
previousValue = currentValue
}
@@ -527,7 +525,7 @@ class NativeAnimatedNodeTraversalTest {
@Test
fun testAnimationCallbackFinish() {
createSimpleAnimatedViewWithOpacity(1000, 0.0)
createSimpleAnimatedViewWithOpacity()
val frames: JavaOnlyArray = JavaOnlyArray.of(0.0, 1.0)
val animationCallback: Callback = mock(Callback::class.java)
@@ -545,8 +543,8 @@ class NativeAnimatedNodeTraversalTest {
nativeAnimatedNodesManager.runUpdates(nextFrameTime())
verify(animationCallback).invoke(callbackResponseCaptor.capture())
assertThat(callbackResponseCaptor.getValue().hasKey("finished")).isTrue()
assertThat(callbackResponseCaptor.getValue().getBoolean("finished")).isTrue()
assertThat(callbackResponseCaptor.value.hasKey("finished")).isTrue
assertThat(callbackResponseCaptor.value.getBoolean("finished")).isTrue
reset(animationCallback)
nativeAnimatedNodesManager.runUpdates(nextFrameTime())
@@ -560,9 +558,9 @@ class NativeAnimatedNodeTraversalTest {
* <p>Add(3) node maps to a "translateX" attribute of the Style(4) node.
*/
private fun createAnimatedGraphWithAdditionNode(
viewTag: Int,
firstValue: Double,
secondValue: Double
viewTag: Int = 50,
firstValue: Double = 100.0,
secondValue: Double = 1000.0
) {
nativeAnimatedNodesManager.createAnimatedNode(
1, JavaOnlyMap.of("type", "value", "value", firstValue, "offset", 0.0))
@@ -585,7 +583,7 @@ class NativeAnimatedNodeTraversalTest {
@Test
fun testAdditionNode() {
createAnimatedGraphWithAdditionNode(50, 100.0, 1000.0)
createAnimatedGraphWithAdditionNode()
val animationCallback: Callback = mock(Callback::class.java)
val frames: JavaOnlyArray = JavaOnlyArray.of(0.0, 1.0)
@@ -606,12 +604,12 @@ class NativeAnimatedNodeTraversalTest {
reset(uiManagerMock)
nativeAnimatedNodesManager.runUpdates(nextFrameTime())
verify(uiManagerMock).synchronouslyUpdateViewOnUIThread(eq(50), stylesCaptor.capture())
assertThat(stylesCaptor.getValue().getDouble("translateX")).isEqualTo(1100.0)
assertThat(stylesCaptor.value.getDouble("translateX")).isEqualTo(1100.0)
reset(uiManagerMock)
nativeAnimatedNodesManager.runUpdates(nextFrameTime())
verify(uiManagerMock).synchronouslyUpdateViewOnUIThread(eq(50), stylesCaptor.capture())
assertThat(stylesCaptor.getValue().getDouble("translateX")).isEqualTo(1111.0)
assertThat(stylesCaptor.value.getDouble("translateX")).isEqualTo(1111.0)
reset(uiManagerMock)
nativeAnimatedNodesManager.runUpdates(nextFrameTime())
@@ -627,7 +625,7 @@ class NativeAnimatedNodeTraversalTest {
*/
@Test
fun testViewReceiveUpdatesIfOneOfAnimationHasntStarted() {
createAnimatedGraphWithAdditionNode(50, 100.0, 1000.0)
createAnimatedGraphWithAdditionNode()
// Start animating only the first addition input node
val animationCallback: Callback = mock(Callback::class.java)
@@ -643,12 +641,12 @@ class NativeAnimatedNodeTraversalTest {
reset(uiManagerMock)
nativeAnimatedNodesManager.runUpdates(nextFrameTime())
verify(uiManagerMock).synchronouslyUpdateViewOnUIThread(eq(50), stylesCaptor.capture())
assertThat(stylesCaptor.getValue().getDouble("translateX")).isEqualTo(1100.0)
assertThat(stylesCaptor.value.getDouble("translateX")).isEqualTo(1100.0)
reset(uiManagerMock)
nativeAnimatedNodesManager.runUpdates(nextFrameTime())
verify(uiManagerMock).synchronouslyUpdateViewOnUIThread(eq(50), stylesCaptor.capture())
assertThat(stylesCaptor.getValue().getDouble("translateX")).isEqualTo(1101.0)
assertThat(stylesCaptor.value.getDouble("translateX")).isEqualTo(1101.0)
reset(uiManagerMock)
nativeAnimatedNodesManager.runUpdates(nextFrameTime())
@@ -665,7 +663,7 @@ class NativeAnimatedNodeTraversalTest {
*/
@Test
fun testViewReceiveUpdatesWhenOneOfAnimationHasFinished() {
createAnimatedGraphWithAdditionNode(50, 100.0, 1000.0)
createAnimatedGraphWithAdditionNode()
val animationCallback: Callback = mock(Callback::class.java)
@@ -690,13 +688,13 @@ class NativeAnimatedNodeTraversalTest {
reset(uiManagerMock)
nativeAnimatedNodesManager.runUpdates(nextFrameTime())
verify(uiManagerMock).synchronouslyUpdateViewOnUIThread(eq(50), stylesCaptor.capture())
assertThat(stylesCaptor.getValue().getDouble("translateX")).isEqualTo(1100.0)
assertThat(stylesCaptor.value.getDouble("translateX")).isEqualTo(1100.0)
for (i in 1 until secondFrames.size()) {
reset(uiManagerMock)
nativeAnimatedNodesManager.runUpdates(nextFrameTime())
verify(uiManagerMock).synchronouslyUpdateViewOnUIThread(eq(50), stylesCaptor.capture())
assertThat(stylesCaptor.getValue().getDouble("translateX"))
assertThat(stylesCaptor.value.getDouble("translateX"))
.isEqualTo(1200.0 + secondFrames.getDouble(i) * 10.0)
}
@@ -741,12 +739,12 @@ class NativeAnimatedNodeTraversalTest {
reset(uiManagerMock)
nativeAnimatedNodesManager.runUpdates(nextFrameTime())
verify(uiManagerMock).synchronouslyUpdateViewOnUIThread(eq(50), stylesCaptor.capture())
assertThat(stylesCaptor.getValue().getDouble("translateX")).isEqualTo(5.0)
assertThat(stylesCaptor.value.getDouble("translateX")).isEqualTo(5.0)
reset(uiManagerMock)
nativeAnimatedNodesManager.runUpdates(nextFrameTime())
verify(uiManagerMock).synchronouslyUpdateViewOnUIThread(eq(50), stylesCaptor.capture())
assertThat(stylesCaptor.getValue().getDouble("translateX")).isEqualTo(20.0)
assertThat(stylesCaptor.value.getDouble("translateX")).isEqualTo(20.0)
reset(uiManagerMock)
nativeAnimatedNodesManager.runUpdates(nextFrameTime())
@@ -760,7 +758,7 @@ class NativeAnimatedNodeTraversalTest {
*/
@Test
fun testHandleStoppingAnimation() {
createSimpleAnimatedViewWithOpacity(1000, 0.0)
createSimpleAnimatedViewWithOpacity()
val frames: JavaOnlyArray = JavaOnlyArray.of(0.0, 0.2, 0.4, 0.6, 0.8, 1.0)
val animationCallback: Callback = mock(Callback::class.java)
@@ -788,14 +786,13 @@ class NativeAnimatedNodeTraversalTest {
verifyNoMoreInteractions(animationCallback)
verifyNoMoreInteractions(uiManagerMock)
assertThat(callbackResponseCaptor.getValue().hasKey("finished")).isTrue()
assertThat(callbackResponseCaptor.getValue().getBoolean("finished")).isFalse()
assertThat(callbackResponseCaptor.value.hasKey("finished")).isTrue
assertThat(callbackResponseCaptor.value.getBoolean("finished")).isFalse
reset(animationCallback)
reset(uiManagerMock)
// Run "update" loop a few more times -> we expect no further updates nor callback calls to
// be
// triggered
// be triggered
for (i in 0 until 5) {
nativeAnimatedNodesManager.runUpdates(nextFrameTime())
}
@@ -859,7 +856,7 @@ class NativeAnimatedNodeTraversalTest {
reset(uiManagerMock)
nativeAnimatedNodesManager.runUpdates(nextFrameTime())
verify(uiManagerMock).synchronouslyUpdateViewOnUIThread(eq(50), stylesCaptor.capture())
assertThat(stylesCaptor.getValue().getDouble("opacity")).isEqualTo(frames.getDouble(i))
assertThat(stylesCaptor.value.getDouble("opacity")).isEqualTo(frames.getDouble(i))
}
reset(uiManagerMock)
@@ -886,7 +883,7 @@ class NativeAnimatedNodeTraversalTest {
fun testNativeAnimatedEventDoUpdate() {
val viewTag: Int = 1000
createSimpleAnimatedViewWithOpacity(viewTag, 0.0)
createSimpleAnimatedViewWithOpacity(viewTag)
nativeAnimatedNodesManager.addAnimatedEventToView(
viewTag,
@@ -901,14 +898,14 @@ class NativeAnimatedNodeTraversalTest {
reset(uiManagerMock)
nativeAnimatedNodesManager.runUpdates(nextFrameTime())
verify(uiManagerMock).synchronouslyUpdateViewOnUIThread(eq(viewTag), stylesCaptor.capture())
assertThat(stylesCaptor.getValue().getDouble("opacity")).isEqualTo(10.0)
assertThat(stylesCaptor.value.getDouble("opacity")).isEqualTo(10.0)
}
@Test
fun testNativeAnimatedEventDoNotUpdate() {
val viewTag: Int = 1000
createSimpleAnimatedViewWithOpacity(viewTag, 0.0)
createSimpleAnimatedViewWithOpacity()
nativeAnimatedNodesManager.addAnimatedEventToView(
viewTag,
@@ -929,14 +926,14 @@ class NativeAnimatedNodeTraversalTest {
reset(uiManagerMock)
nativeAnimatedNodesManager.runUpdates(nextFrameTime())
verify(uiManagerMock).synchronouslyUpdateViewOnUIThread(eq(viewTag), stylesCaptor.capture())
assertThat(stylesCaptor.getValue().getDouble("opacity")).isEqualTo(0.0)
assertThat(stylesCaptor.value.getDouble("opacity")).isEqualTo(0.0)
}
@Test
fun testNativeAnimatedEventCustomMapping() {
val viewTag: Int = 1000
whenever(uiManagerMock.getConstants()).thenAnswer {
whenever(uiManagerMock.constants).thenAnswer {
MapBuilder.of(
"customDirectEventTypes",
MapBuilder.of("onScroll", MapBuilder.of("registrationName", "onScroll")))
@@ -944,7 +941,7 @@ class NativeAnimatedNodeTraversalTest {
nativeAnimatedNodesManager = NativeAnimatedNodesManager(reactApplicationContextMock)
createSimpleAnimatedViewWithOpacity(viewTag, 0.0)
createSimpleAnimatedViewWithOpacity()
nativeAnimatedNodesManager.addAnimatedEventToView(
viewTag,
@@ -959,9 +956,10 @@ class NativeAnimatedNodeTraversalTest {
reset(uiManagerMock)
nativeAnimatedNodesManager.runUpdates(nextFrameTime())
verify(uiManagerMock).synchronouslyUpdateViewOnUIThread(eq(viewTag), stylesCaptor.capture())
assertThat(stylesCaptor.getValue().getDouble("opacity")).isEqualTo(10.0)
assertThat(stylesCaptor.value.getDouble("opacity")).isEqualTo(10.0)
}
@SuppressLint("CheckResult")
@Test
fun testRestoreDefaultProps() {
val viewTag: Int = 1001
@@ -990,12 +988,12 @@ class NativeAnimatedNodeTraversalTest {
}
verify(uiManagerMock).synchronouslyUpdateViewOnUIThread(eq(viewTag), stylesCaptor.capture())
assertThat(stylesCaptor.getValue().getDouble("opacity")).isEqualTo(0.0)
assertThat(stylesCaptor.value.getDouble("opacity")).isEqualTo(0.0)
reset(uiManagerMock)
nativeAnimatedNodesManager.restoreDefaultValues(propsNodeTag)
verify(uiManagerMock).synchronouslyUpdateViewOnUIThread(eq(viewTag), stylesCaptor.capture())
assertThat(stylesCaptor.getValue().isNull("opacity"))
assertThat(stylesCaptor.value.isNull("opacity")).isTrue
}
/**
@@ -1005,9 +1003,9 @@ class NativeAnimatedNodeTraversalTest {
* <p>Value(3) is set to track Value(1) via Tracking(2) node with the provided animation config
*/
private fun createAnimatedGraphWithTrackingNode(
viewTag: Int,
initialValue: Double,
animationConfig: JavaOnlyMap
animationConfig: JavaOnlyMap,
viewTag: Int = 1000,
initialValue: Double = 0.0,
) {
nativeAnimatedNodesManager.createAnimatedNode(
1, JavaOnlyMap.of("type", "value", "value", initialValue, "offset", 0.0))
@@ -1048,14 +1046,14 @@ class NativeAnimatedNodeTraversalTest {
val frames: JavaOnlyArray = JavaOnlyArray.of(0.0, 0.25, 0.5, 0.75, 1)
val animationConfig: JavaOnlyMap = JavaOnlyMap.of("type", "frames", "frames", frames)
createAnimatedGraphWithTrackingNode(1000, 0.0, animationConfig)
createAnimatedGraphWithTrackingNode(animationConfig)
val stylesCaptor: ArgumentCaptor<ReadableMap> = ArgumentCaptor.forClass(ReadableMap::class.java)
reset(uiManagerMock)
nativeAnimatedNodesManager.runUpdates(nextFrameTime())
verify(uiManagerMock).synchronouslyUpdateViewOnUIThread(eq(1000), stylesCaptor.capture())
assertThat(stylesCaptor.getValue().getDouble("translateX")).isEqualTo(0.0)
assertThat(stylesCaptor.value.getDouble("translateX")).isEqualTo(0.0)
// update "toValue" to 100, we expect tracking animation to animate now from 0 to 100 in 5
// steps
@@ -1067,8 +1065,7 @@ class NativeAnimatedNodeTraversalTest {
reset(uiManagerMock)
nativeAnimatedNodesManager.runUpdates(nextFrameTime())
verify(uiManagerMock).synchronouslyUpdateViewOnUIThread(eq(1000), stylesCaptor.capture())
assertThat(stylesCaptor.getValue().getDouble("translateX"))
.isEqualTo(frames.getDouble(i) * 100.0)
assertThat(stylesCaptor.value.getDouble("translateX")).isEqualTo(frames.getDouble(i) * 100.0)
}
// update "toValue" to 0 but run only two frames from the animation,
@@ -1081,12 +1078,12 @@ class NativeAnimatedNodeTraversalTest {
reset(uiManagerMock)
nativeAnimatedNodesManager.runUpdates(nextFrameTime())
verify(uiManagerMock).synchronouslyUpdateViewOnUIThread(eq(1000), stylesCaptor.capture())
assertThat(stylesCaptor.getValue().getDouble("translateX"))
assertThat(stylesCaptor.value.getDouble("translateX"))
.isEqualTo(100 * (1 - frames.getDouble(i)))
}
// at this point we expect tracking value to be at 75
assertThat((nativeAnimatedNodesManager.getNodeById(3) as ValueAnimatedNode).getValue())
assertThat((nativeAnimatedNodesManager.getNodeById(3) as ValueAnimatedNode).value)
.isEqualTo(75.0)
// we update "toValue" again to 100 and expect the animation to restart from the current
@@ -1099,7 +1096,7 @@ class NativeAnimatedNodeTraversalTest {
reset(uiManagerMock)
nativeAnimatedNodesManager.runUpdates(nextFrameTime())
verify(uiManagerMock).synchronouslyUpdateViewOnUIThread(eq(1000), stylesCaptor.capture())
assertThat(stylesCaptor.getValue().getDouble("translateX"))
assertThat(stylesCaptor.value.getDouble("translateX"))
.isEqualTo(50.0 + 50.0 * frames.getDouble(i))
}
}
@@ -1116,14 +1113,14 @@ class NativeAnimatedNodeTraversalTest {
val frames: JavaOnlyArray = JavaOnlyArray.of(0.0, 0.5, 1.0)
val animationConfig: JavaOnlyMap = JavaOnlyMap.of("type", "frames", "frames", frames)
createAnimatedGraphWithTrackingNode(1000, 0.0, animationConfig)
createAnimatedGraphWithTrackingNode(animationConfig)
nativeAnimatedNodesManager.setAnimatedNodeValue(1, 100.0)
nativeAnimatedNodesManager.runUpdates(nextFrameTime())
// make sure animation starts
reset(uiManagerMock)
for (i in 0 until frames.size()) {
assertThat(nativeAnimatedNodesManager.hasActiveAnimations()).isTrue()
assertThat(nativeAnimatedNodesManager.hasActiveAnimations()).isTrue
nativeAnimatedNodesManager.runUpdates(nextFrameTime())
}
verify(uiManagerMock, times(frames.size()))
@@ -1131,7 +1128,7 @@ class NativeAnimatedNodeTraversalTest {
// the animation has completed, we expect no updates to be done
reset(uiManagerMock)
assertThat(nativeAnimatedNodesManager.hasActiveAnimations()).isFalse()
assertThat(nativeAnimatedNodesManager.hasActiveAnimations()).isFalse
nativeAnimatedNodesManager.runUpdates(nextFrameTime())
verifyNoMoreInteractions(uiManagerMock)
@@ -1142,7 +1139,7 @@ class NativeAnimatedNodeTraversalTest {
reset(uiManagerMock)
for (i in 0 until frames.size()) {
assertThat(nativeAnimatedNodesManager.hasActiveAnimations()).isTrue()
assertThat(nativeAnimatedNodesManager.hasActiveAnimations()).isTrue
nativeAnimatedNodesManager.runUpdates(nextFrameTime())
}
verify(uiManagerMock, times(frames.size()))
@@ -1150,7 +1147,7 @@ class NativeAnimatedNodeTraversalTest {
// the animation has completed, we expect no updates to be done
reset(uiManagerMock)
assertThat(nativeAnimatedNodesManager.hasActiveAnimations()).isFalse()
assertThat(nativeAnimatedNodesManager.hasActiveAnimations()).isFalse
nativeAnimatedNodesManager.runUpdates(nextFrameTime())
verifyNoMoreInteractions(uiManagerMock)
}
@@ -1184,7 +1181,7 @@ class NativeAnimatedNodeTraversalTest {
"overshootClamping",
false)
createAnimatedGraphWithTrackingNode(1000, 0.0, springConfig)
createAnimatedGraphWithTrackingNode(springConfig)
// update "toValue" to 1, we expect tracking animation to animate now from 0 to 1
nativeAnimatedNodesManager.setAnimatedNodeValue(1, 1.0)
@@ -1194,18 +1191,18 @@ class NativeAnimatedNodeTraversalTest {
// passes the final point (that is 1) while going backwards
var isBoucingBack: Boolean = false
var previousValue: Double =
(nativeAnimatedNodesManager.getNodeById(3) as ValueAnimatedNode).getValue()
(nativeAnimatedNodesManager.getNodeById(3) as ValueAnimatedNode).value
for (i in 500 downTo 0) {
nativeAnimatedNodesManager.runUpdates(nextFrameTime())
val currentValue: Double =
(nativeAnimatedNodesManager.getNodeById(3) as ValueAnimatedNode).getValue()
(nativeAnimatedNodesManager.getNodeById(3) as ValueAnimatedNode).value
if (previousValue >= 1.0 && currentValue < 1.0) {
isBoucingBack = true
break
}
previousValue = currentValue
}
assertThat(isBoucingBack).isTrue()
assertThat(isBoucingBack).isTrue
// we now update "toValue" to 1.5 but since the value have negative speed and has also
// pretty
@@ -1219,7 +1216,7 @@ class NativeAnimatedNodeTraversalTest {
for (i in 0 until 8 * 60) {
nativeAnimatedNodesManager.runUpdates(nextFrameTime())
val currentValue: Double =
(nativeAnimatedNodesManager.getNodeById(3) as ValueAnimatedNode).getValue()
(nativeAnimatedNodesManager.getNodeById(3) as ValueAnimatedNode).value
if (!hasTurnedForward) {
if (currentValue <= previousValue) {
bounceBackInitialFrames++
@@ -1235,4 +1232,9 @@ class NativeAnimatedNodeTraversalTest {
// we verify that the value settled at 2
assertThat(previousValue).isEqualTo(1.5)
}
companion object {
private const val FRAME_LEN_NANOS: Long = 1000000000L / 60L
private const val INITIAL_FRAME_TIME_NANOS: Long = 14599233201256L /* random */
}
}