Convert ReactPropConstantsTest to Kotlin (#39005)

Summary:
Converts ReactPropConstantsTest to Kotlin, as requested in https://github.com/facebook/react-native/issues/38825

## Changelog:

<!-- Help reviewers and the release process by writing your own changelog entry.

Pick one each for the category and type tags:

[ANDROID|GENERAL|IOS|INTERNAL] [BREAKING|ADDED|CHANGED|DEPRECATED|REMOVED|FIXED|SECURITY] - Message

For more details, see:
https://reactnative.dev/contributing/changelogs-in-pull-requests
-->

[INTERNAL] [CHANGED] - Convert ReactPropConstantsTest to Kotlin
[INTERNAL] [CHANGED] - Add null-check to ViewManagersPropertyCache.java

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

Test Plan:
1. Run `./gradlew :packages:react-native:ReactAndroid:test`.
2. All tests should pass.

Reviewed By: mdvacca, rshest

Differential Revision: D48430460

Pulled By: cortinico

fbshipit-source-id: cc425f14bf15ec6e5a334c631d52ca962d06a2a9
This commit is contained in:
Thiago Brezinski
2023-08-17 11:02:29 -07:00
committed by Facebook GitHub Bot
parent 10feddcf03
commit 4a48fd2bb5
3 changed files with 135 additions and 159 deletions
@@ -393,6 +393,11 @@ import java.util.Map;
*/
/*package*/ static Map<String, PropSetter> getNativePropSettersForShadowNodeClass(
Class<? extends ReactShadowNode> cls) {
if (cls == null) {
return EMPTY_PROPS_MAP;
}
;
for (Class iface : cls.getInterfaces()) {
if (iface == ReactShadowNode.class) {
return EMPTY_PROPS_MAP;
@@ -1,159 +0,0 @@
/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
package com.facebook.react.uimanager;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.fail;
import android.view.View;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReadableArray;
import com.facebook.react.bridge.ReadableMap;
import com.facebook.react.common.MapBuilder;
import com.facebook.react.uimanager.annotations.ReactProp;
import com.facebook.react.uimanager.annotations.ReactPropGroup;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
/** Verifies that prop constants are generated properly based on {@code ReactProp} annotation. */
@RunWith(RobolectricTestRunner.class)
@Ignore // TODO T14964130
public class ReactPropConstantsTest {
private class ViewManagerUnderTest extends ViewManager<View, ReactShadowNode> {
@Override
public String getName() {
return "SomeView";
}
@Override
public ReactShadowNode createShadowNodeInstance() {
fail("This method should not be executed as a part of this test");
return null;
}
@Override
protected View createViewInstance(ThemedReactContext reactContext) {
fail("This method should not be executed as a part of this test");
return null;
}
@Override
public Class<? extends ReactShadowNode> getShadowNodeClass() {
return ReactShadowNode.class;
}
@Override
public void updateExtraData(View root, Object extraData) {
fail("This method should not be executed as a part of this test");
}
@ReactProp(name = "boolProp")
public void setBoolProp(View v, boolean value) {}
@ReactProp(name = "intProp")
public void setIntProp(View v, int value) {}
@ReactProp(name = "floatProp")
public void setFloatProp(View v, float value) {}
@ReactProp(name = "doubleProp")
public void setDoubleProp(View v, double value) {}
@ReactProp(name = "stringProp")
public void setStringProp(View v, String value) {}
@ReactProp(name = "boxedBoolProp")
public void setBoxedBoolProp(View v, Boolean value) {}
@ReactProp(name = "boxedIntProp")
public void setBoxedIntProp(View v, Integer value) {}
@ReactProp(name = "arrayProp")
public void setArrayProp(View v, ReadableArray value) {}
@ReactProp(name = "mapProp")
public void setMapProp(View v, ReadableMap value) {}
@ReactPropGroup(
names = {
"floatGroupPropFirst",
"floatGroupPropSecond",
})
public void setFloatGroupProp(View v, int index, float value) {}
@ReactPropGroup(names = {"intGroupPropFirst", "intGroupPropSecond"})
public void setIntGroupProp(View v, int index, int value) {}
@ReactPropGroup(
names = {
"boxedIntGroupPropFirst",
"boxedIntGroupPropSecond",
})
public void setBoxedIntGroupProp(View v, int index, Integer value) {}
@ReactProp(name = "customIntProp", customType = "date")
public void customIntProp(View v, int value) {}
@ReactPropGroup(
names = {"customBoxedIntGroupPropFirst", "customBoxedIntGroupPropSecond"},
customType = "color")
public void customIntGroupProp(View v, int index, Integer value) {}
}
@Test
public void testNativePropsIncludeCorrectTypes() {
List<ViewManager> viewManagers = Arrays.<ViewManager>asList(new ViewManagerUnderTest());
ReactApplicationContext reactContext =
new ReactApplicationContext(RuntimeEnvironment.getApplication());
UIManagerModule uiManagerModule = new UIManagerModule(reactContext, viewManagers, 0);
Map<String, String> constants =
(Map) valueAtPath(uiManagerModule.getConstants(), "SomeView", "NativeProps");
assertThat(constants)
.isEqualTo(
MapBuilder.<String, String>builder()
.put("boolProp", "boolean")
.put("intProp", "number")
.put("doubleProp", "number")
.put("floatProp", "number")
.put("stringProp", "String")
.put("boxedBoolProp", "boolean")
.put("boxedIntProp", "number")
.put("arrayProp", "Array")
.put("mapProp", "Map")
.put("floatGroupPropFirst", "number")
.put("floatGroupPropSecond", "number")
.put("intGroupPropFirst", "number")
.put("intGroupPropSecond", "number")
.put("boxedIntGroupPropFirst", "number")
.put("boxedIntGroupPropSecond", "number")
.put("customIntProp", "date")
.put("customBoxedIntGroupPropFirst", "color")
.put("customBoxedIntGroupPropSecond", "color")
.build());
}
private static Object valueAtPath(Map nestedMap, String... keyPath) {
assertThat(keyPath).isNotEmpty();
Object value = nestedMap;
for (String key : keyPath) {
assertThat(value).isInstanceOf(Map.class);
nestedMap = (Map) value;
assertThat(nestedMap).containsKey(key);
value = nestedMap.get(key);
}
return value;
}
}
@@ -0,0 +1,130 @@
/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
package com.facebook.react.uimanager
import android.view.View
import com.facebook.react.bridge.ReactApplicationContext
import com.facebook.react.bridge.ReadableArray
import com.facebook.react.bridge.ReadableMap
import com.facebook.react.common.MapBuilder
import com.facebook.react.uimanager.annotations.ReactProp
import com.facebook.react.uimanager.annotations.ReactPropGroup
import org.assertj.core.api.Assertions
import org.junit.Test
import org.junit.runner.RunWith
import org.robolectric.RobolectricTestRunner
import org.robolectric.RuntimeEnvironment
/** Verifies that prop constants are generated properly based on `ReactProp` annotation. */
@RunWith(RobolectricTestRunner::class)
class ReactPropConstantsTest {
@Suppress("UNUSED_PARAMETER")
private inner class ViewManagerUnderTest : ViewManager<View?, ReactShadowNode<*>?>() {
override fun getName(): String {
return "SomeView"
}
override fun createShadowNodeInstance(): ReactShadowNode<*>? {
Assertions.fail<Any>("This method should not be executed as a part of this test")
return null
}
override fun createViewInstance(reactContext: ThemedReactContext): View {
Assertions.fail<Any>("This method should not be executed as a part of this test")
return View(reactContext)
}
override fun getShadowNodeClass(): Class<out ReactShadowNode<*>> {
return ReactShadowNode::class.java
}
override fun updateExtraData(root: View, extraData: Any) {
Assertions.fail<Any>("This method should not be executed as a part of this test")
}
@ReactProp(name = "boolProp") fun setBoolProp(v: View?, value: Boolean) {}
@ReactProp(name = "intProp") fun setIntProp(v: View?, value: Int) {}
@ReactProp(name = "floatProp") fun setFloatProp(v: View?, value: Float) {}
@ReactProp(name = "doubleProp") fun setDoubleProp(v: View?, value: Double) {}
@ReactProp(name = "stringProp") fun setStringProp(v: View?, value: String?) {}
@ReactProp(name = "boxedBoolProp") fun setBoxedBoolProp(v: View?, value: Boolean?) {}
@ReactProp(name = "boxedIntProp") fun setBoxedIntProp(v: View?, value: Int?) {}
@ReactProp(name = "arrayProp") fun setArrayProp(v: View?, value: ReadableArray?) {}
@ReactProp(name = "mapProp") fun setMapProp(v: View?, value: ReadableMap?) {}
@ReactPropGroup(names = ["floatGroupPropFirst", "floatGroupPropSecond"])
fun setFloatGroupProp(v: View?, index: Int, value: Float) {}
@ReactPropGroup(names = ["intGroupPropFirst", "intGroupPropSecond"])
fun setIntGroupProp(v: View?, index: Int, value: Int) {}
@ReactPropGroup(names = ["boxedIntGroupPropFirst", "boxedIntGroupPropSecond"])
fun setBoxedIntGroupProp(v: View?, index: Int, value: Int?) {}
@ReactProp(name = "customIntProp", customType = "date")
fun customIntProp(v: View?, value: Int) {}
@ReactPropGroup(
names = ["customBoxedIntGroupPropFirst", "customBoxedIntGroupPropSecond"],
customType = "color")
fun customIntGroupProp(v: View?, index: Int, value: Int?) {}
}
@Test
fun testNativePropsIncludeCorrectTypes() {
val viewManagers = listOf<ViewManager<*, *>>(ViewManagerUnderTest())
val reactContext = ReactApplicationContext(RuntimeEnvironment.getApplication())
val uiManagerModule = UIManagerModule(reactContext, viewManagers, 0)
val constants: Map<*, *> =
valueAtPath(uiManagerModule.constants as Map<*, *>, "SomeView", "NativeProps")
Assertions.assertThat(constants)
.isEqualTo(
MapBuilder.builder<String, String>()
.put("boolProp", "boolean")
.put("intProp", "number")
.put("doubleProp", "number")
.put("floatProp", "number")
.put("stringProp", "String")
.put("boxedBoolProp", "boolean")
.put("boxedIntProp", "number")
.put("arrayProp", "Array")
.put("mapProp", "Map")
.put("floatGroupPropFirst", "number")
.put("floatGroupPropSecond", "number")
.put("intGroupPropFirst", "number")
.put("intGroupPropSecond", "number")
.put("boxedIntGroupPropFirst", "number")
.put("boxedIntGroupPropSecond", "number")
.put("customIntProp", "date")
.put("customBoxedIntGroupPropFirst", "color")
.put("customBoxedIntGroupPropSecond", "color")
.build())
}
companion object {
private fun valueAtPath(nestedMap: Map<*, *>, vararg keyPath: String): Map<*, *> {
require(keyPath.isNotEmpty()) { "keyPath must not be empty" }
var value: Map<*, *> = nestedMap
for (key in keyPath) {
require(key in value) { "Key '$key' not found in the map" }
require(value[key] is Map<*, *>) { "Key '$key' must be a map itself" }
value = value[key] as Map<*, *>
}
return value
}
}
}