diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/UIManagerModuleConstantsHelper.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/UIManagerModuleConstantsHelper.java index 988cc7c2ee0..d4f70672e9f 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/UIManagerModuleConstantsHelper.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/UIManagerModuleConstantsHelper.java @@ -53,7 +53,7 @@ public class UIManagerModuleConstantsHelper { } private static void validateDirectEventNames( - String viewManagerName, Map directEvents) { + String viewManagerName, @Nullable Map directEvents) { if (!ReactBuildConfig.DEBUG || directEvents == null) { return; } @@ -139,7 +139,7 @@ public class UIManagerModuleConstantsHelper { // For Fabric, events needs to be fired with a "top" prefix. // For the sake of Fabric Interop, here we normalize events adding "top" in their // name if the user hasn't provided it. - normalizeEventTypes(viewManagerBubblingEvents); + viewManagerBubblingEvents = normalizeEventTypes(viewManagerBubblingEvents); } recursiveMerge(cumulativeBubblingEventTypes, viewManagerBubblingEvents); recursiveMerge(viewManagerBubblingEvents, defaultBubblingEvents); @@ -155,7 +155,7 @@ public class UIManagerModuleConstantsHelper { // For Fabric, events needs to be fired with a "top" prefix. // For the sake of Fabric Interop, here we normalize events adding "top" in their // name if the user hasn't provided it. - normalizeEventTypes(viewManagerDirectEvents); + viewManagerDirectEvents = normalizeEventTypes(viewManagerDirectEvents); } recursiveMerge(cumulativeDirectEventTypes, viewManagerDirectEvents); recursiveMerge(viewManagerDirectEvents, defaultDirectEvents); @@ -181,9 +181,9 @@ public class UIManagerModuleConstantsHelper { } @VisibleForTesting - /* package */ static void normalizeEventTypes(@Nullable Map events) { + /* package */ static @Nullable Map normalizeEventTypes(@Nullable Map events) { if (events == null) { - return; + return null; } Set keysToNormalize = new HashSet<>(); for (Object key : events.keySet()) { @@ -212,6 +212,7 @@ public class UIManagerModuleConstantsHelper { String newKey = "top" + baseKey; events.put(newKey, value); } + return events; } /** Merges {@param source} map into {@param dest} map recursively */ diff --git a/packages/react-native/ReactAndroid/src/test/java/com/facebook/react/uimanager/UIManagerModuleConstantsHelperTest.kt b/packages/react-native/ReactAndroid/src/test/java/com/facebook/react/uimanager/UIManagerModuleConstantsHelperTest.kt index c5edeacb901..fbb5f43872e 100644 --- a/packages/react-native/ReactAndroid/src/test/java/com/facebook/react/uimanager/UIManagerModuleConstantsHelperTest.kt +++ b/packages/react-native/ReactAndroid/src/test/java/com/facebook/react/uimanager/UIManagerModuleConstantsHelperTest.kt @@ -13,28 +13,28 @@ import org.junit.Test class UIManagerModuleConstantsHelperTest { @Test fun normalizeEventTypes_withNull_doesNothing() { - UIManagerModuleConstantsHelper.normalizeEventTypes(null) + assertThat(UIManagerModuleConstantsHelper.normalizeEventTypes(null)).isNull() } @Test fun normalizeEventTypes_withEmptyMap_doesNothing() { val emptyMap = mutableMapOf() - UIManagerModuleConstantsHelper.normalizeEventTypes(emptyMap) - assertThat(emptyMap.isEmpty()).isTrue() + assertThat(UIManagerModuleConstantsHelper.normalizeEventTypes(emptyMap)).isEmpty() } @Test fun normalizeEventTypes_withOnEvent_doesNormalize() { val onClickMap = mutableMapOf("onClick" to "¯\\_(ツ)_/¯") - UIManagerModuleConstantsHelper.normalizeEventTypes(onClickMap) - assertThat(onClickMap).containsKeys("topClick", "onClick") + assertThat(UIManagerModuleConstantsHelper.normalizeEventTypes(onClickMap)) + .containsKeys("topClick", "onClick") } @Test fun normalizeEventTypes_withTopEvent_doesNormalize() { val onClickMap = mutableMapOf("topOnClick" to "¯\\_(ツ)_/¯") - UIManagerModuleConstantsHelper.normalizeEventTypes(onClickMap) - assertThat(onClickMap).containsKey("topOnClick").doesNotContainKey("onClick") + assertThat(UIManagerModuleConstantsHelper.normalizeEventTypes(onClickMap)) + .containsKey("topOnClick") + .doesNotContainKey("onClick") } @Suppress("UNCHECKED_CAST") @@ -49,25 +49,27 @@ class UIManagerModuleConstantsHelperTest { "bubbled" to "onColorChanged", "captured" to "onColorChangedCapture", ))) - UIManagerModuleConstantsHelper.normalizeEventTypes(nestedObjects) - assertThat(nestedObjects).containsKey("topColorChanged") - var innerMap = nestedObjects["topColorChanged"] - assertThat(innerMap).isNotNull() - requireNotNull(innerMap) + val result = + checkNotNull( + UIManagerModuleConstantsHelper.normalizeEventTypes(nestedObjects) + as Map>>) { + "returned map was null" + } + verifyNestedObjects(result, "topColorChanged") + verifyNestedObjects(result, "onColorChanged") + } + + private fun verifyNestedObjects( + nestedObjects: Map>>, + name: String, + ) { + assertThat(nestedObjects).containsKey(name) + val innerMap = checkNotNull(nestedObjects[name]) { """nestedObjects["$name"] is null""" } assertThat(innerMap).containsKey("phasedRegistrationNames") - var innerInnerMap = innerMap["phasedRegistrationNames"] - assertThat(innerInnerMap).isNotNull() - requireNotNull(innerInnerMap) - assertThat("onColorChanged").isEqualTo(innerInnerMap["bubbled"]) - assertThat("onColorChangedCapture").isEqualTo(innerInnerMap["captured"]) - assertThat(nestedObjects).containsKey("onColorChanged") - innerMap = nestedObjects["topColorChanged"] - assertThat(innerMap).isNotNull() - requireNotNull(innerMap) - assertThat(innerMap).containsKey("phasedRegistrationNames") - innerInnerMap = innerMap["phasedRegistrationNames"] - assertThat(innerInnerMap).isNotNull() - requireNotNull(innerInnerMap) + val innerInnerMap = + checkNotNull(innerMap["phasedRegistrationNames"]) { + """nestedObjects["$name"]["phasedRegistrationNames"] is null""" + } assertThat("onColorChanged").isEqualTo(innerInnerMap["bubbled"]) assertThat("onColorChangedCapture").isEqualTo(innerInnerMap["captured"]) }