Files
react-native/ReactAndroid/src/test/java/com/facebook/react/uimanager/ReactPropAnnotationSetterTest.java
T
Krzysztof Magiera 788e25894e Move SimpleArray and SimpleMap from test to src.
Summary:
As a part of this change I'm also renaming SimpleArray to JavaOnlyArray and SimpleMap to JavaOnlyMap. The main reason for the change is to support use-cases such as driving animations form the native code. In the case of native "animated" I'd like to be able to use the same interface as JS is using for updating the View properties. As view setters can take ReadableMap and ReadableArray as an argument in some cases it is necessary to create and pass those types to the setter. Using WritableNativeArray and WritableNativeMap for this purpose seems to me like a misuse and IMO will be less performant (vs java-only map/array) as those implementations of ReadableMap and ReadableArray proxies all their methods through JNI.

I'm also adding some additional class-level comments for the moved classes to avoid confusion and hopefuly prevent people from using those classess accidentally while writing native modules or methods that calls to JS.
Closes https://github.com/facebook/react-native/pull/5816

Reviewed By: svcscm

Differential Revision: D2911339

Pulled By: foghina

fb-gh-sync-id: 5b9a98d64f48d8bba34c15e3eecba2151da3577a
shipit-source-id: 5b9a98d64f48d8bba34c15e3eecba2151da3577a
2016-02-09 08:18:21 -08:00

494 lines
18 KiB
Java

/**
* Copyright (c) 2015-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/
package com.facebook.react.uimanager;
import android.view.View;
import com.facebook.react.bridge.JSApplicationIllegalArgumentException;
import com.facebook.react.bridge.ReadableArray;
import com.facebook.react.bridge.ReadableMap;
import com.facebook.react.bridge.JavaOnlyArray;
import com.facebook.react.bridge.JavaOnlyMap;
import com.facebook.react.uimanager.annotations.ReactProp;
import com.facebook.react.uimanager.annotations.ReactPropGroup;
import org.junit.Before;
import org.junit.runner.RunWith;
import org.junit.Rule;
import org.junit.Test;
import org.powermock.core.classloader.annotations.PowerMockIgnore;
import org.powermock.modules.junit4.rule.PowerMockRule;
import org.robolectric.RobolectricTestRunner;
import static org.fest.assertions.api.Assertions.fail;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoMoreInteractions;
/**
* Test updating view through {@link ViewManager} with {@link ReactProp} and {@link ReactPropGroup}
* annotations.
*/
@RunWith(RobolectricTestRunner.class)
@PowerMockIgnore({"org.mockito.*", "org.robolectric.*", "android.*"})
public class ReactPropAnnotationSetterTest {
@Rule
public PowerMockRule rule = new PowerMockRule();
public interface ViewManagerUpdatesReceiver {
void onBooleanSetterCalled(boolean value);
void onIntSetterCalled(int value);
void onDoubleSetterCalled(double value);
void onFloatSetterCalled(float value);
void onStringSetterCalled(String value);
void onBoxedBooleanSetterCalled(Boolean value);
void onBoxedIntSetterCalled(Integer value);
void onArraySetterCalled(ReadableArray value);
void onMapSetterCalled(ReadableMap value);
void onFloatGroupPropSetterCalled(int index, float value);
void onIntGroupPropSetterCalled(int index, int value);
void onBoxedIntGroupPropSetterCalled(int index, Integer value);
}
private class ViewManagerUnderTest extends ViewManager<View, ReactShadowNode> {
final ViewManagerUpdatesReceiver mViewManagerUpdatesReceiver;
private ViewManagerUnderTest(ViewManagerUpdatesReceiver viewManagerUpdatesReceiver) {
mViewManagerUpdatesReceiver = viewManagerUpdatesReceiver;
}
@Override
public String getName() {
return "RedpandasLivestreamVideoView";
}
@Override
public ReactShadowNode createShadowNodeInstance() {
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
protected View createViewInstance(ThemedReactContext reactContext) {
fail("This method should not be executed as a part of this test");
return null;
}
@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) {
mViewManagerUpdatesReceiver.onBooleanSetterCalled(value);
}
@ReactProp(name = "boolPropWithDefault", defaultBoolean = true)
public void setBoolPropWithDefault(View v, boolean value) {
mViewManagerUpdatesReceiver.onBooleanSetterCalled(value);
}
@ReactProp(name = "intProp")
public void setIntProp(View v, int value) {
mViewManagerUpdatesReceiver.onIntSetterCalled(value);
}
@ReactProp(name = "intPropWithDefault", defaultInt = 7168)
public void setIntPropWithDefault(View v, int value) {
mViewManagerUpdatesReceiver.onIntSetterCalled(value);
}
@ReactProp(name = "floatProp")
public void setFloatProp(View v, float value) {
mViewManagerUpdatesReceiver.onFloatSetterCalled(value);
}
@ReactProp(name = "floatPropWithDefault", defaultFloat = 14.0f)
public void setFloatPropWithDefault(View v, float value) {
mViewManagerUpdatesReceiver.onFloatSetterCalled(value);
}
@ReactProp(name = "doubleProp")
public void setDoubleProp(View v, double value) {
mViewManagerUpdatesReceiver.onDoubleSetterCalled(value);
}
@ReactProp(name = "doublePropWithDefault", defaultDouble = -88.0)
public void setDoublePropWithDefault(View v, double value) {
mViewManagerUpdatesReceiver.onDoubleSetterCalled(value);
}
@ReactProp(name = "stringProp")
public void setStringProp(View v, String value) {
mViewManagerUpdatesReceiver.onStringSetterCalled(value);
}
@ReactProp(name = "boxedBoolProp")
public void setBoxedBoolProp(View v, Boolean value) {
mViewManagerUpdatesReceiver.onBoxedBooleanSetterCalled(value);
}
@ReactProp(name = "boxedIntProp")
public void setBoxedIntProp(View v, Integer value) {
mViewManagerUpdatesReceiver.onBoxedIntSetterCalled(value);
}
@ReactProp(name = "arrayProp")
public void setArrayProp(View v, ReadableArray value) {
mViewManagerUpdatesReceiver.onArraySetterCalled(value);
}
@ReactProp(name = "mapProp")
public void setMapProp(View v, ReadableMap value) {
mViewManagerUpdatesReceiver.onMapSetterCalled(value);
}
@ReactPropGroup(names = {
"floatGroupPropFirst",
"floatGroupPropSecond",
})
public void setFloatGroupProp(View v, int index, float value) {
mViewManagerUpdatesReceiver.onFloatGroupPropSetterCalled(index, value);
}
@ReactPropGroup(names = {
"floatGroupPropWithDefaultFirst",
"floatGroupPropWithDefaultSecond",
}, defaultFloat = -100.0f)
public void setFloatGroupPropWithDefault(View v, int index, float value) {
mViewManagerUpdatesReceiver.onFloatGroupPropSetterCalled(index, value);
}
@ReactPropGroup(names = {
"intGroupPropFirst",
"intGroupPropSecond"
})
public void setIntGroupProp(View v, int index, int value) {
mViewManagerUpdatesReceiver.onIntGroupPropSetterCalled(index, value);
}
@ReactPropGroup(names = {
"intGroupPropWithDefaultFirst",
"intGroupPropWithDefaultSecond"
}, defaultInt = 555)
public void setIntGroupPropWithDefault(View v, int index, int value) {
mViewManagerUpdatesReceiver.onIntGroupPropSetterCalled(index, value);
}
@ReactPropGroup(names = {
"boxedIntGroupPropFirst",
"boxedIntGroupPropSecond",
})
public void setBoxedIntGroupProp(View v, int index, Integer value) {
mViewManagerUpdatesReceiver.onBoxedIntGroupPropSetterCalled(index, value);
}
}
public static ReactStylesDiffMap buildStyles(Object... keysAndValues) {
return new ReactStylesDiffMap(JavaOnlyMap.of(keysAndValues));
}
private ViewManagerUnderTest mViewManager;
private ViewManagerUpdatesReceiver mUpdatesReceiverMock;
@Before
public void setup() {
mUpdatesReceiverMock = mock(ViewManagerUpdatesReceiver.class);
mViewManager = new ViewManagerUnderTest(mUpdatesReceiverMock);
}
@Test
public void testBooleanSetter() {
mViewManager.updateProperties(null, buildStyles("boolProp", true));
verify(mUpdatesReceiverMock).onBooleanSetterCalled(true);
verifyNoMoreInteractions(mUpdatesReceiverMock);
reset(mUpdatesReceiverMock);
mViewManager.updateProperties(null, buildStyles("boolProp", false));
verify(mUpdatesReceiverMock).onBooleanSetterCalled(false);
verifyNoMoreInteractions(mUpdatesReceiverMock);
reset(mUpdatesReceiverMock);
mViewManager.updateProperties(null, buildStyles("boolProp", null));
verify(mUpdatesReceiverMock).onBooleanSetterCalled(false);
verifyNoMoreInteractions(mUpdatesReceiverMock);
reset(mUpdatesReceiverMock);
mViewManager.updateProperties(null, buildStyles("boolPropWithDefault", false));
verify(mUpdatesReceiverMock).onBooleanSetterCalled(false);
verifyNoMoreInteractions(mUpdatesReceiverMock);
reset(mUpdatesReceiverMock);
mViewManager.updateProperties(null, buildStyles("boolPropWithDefault", null));
verify(mUpdatesReceiverMock).onBooleanSetterCalled(true);
verifyNoMoreInteractions(mUpdatesReceiverMock);
reset(mUpdatesReceiverMock);
}
@Test
public void testIntSetter() {
mViewManager.updateProperties(null, buildStyles("intProp", 13));
verify(mUpdatesReceiverMock).onIntSetterCalled(13);
verifyNoMoreInteractions(mUpdatesReceiverMock);
reset(mUpdatesReceiverMock);
mViewManager.updateProperties(null, buildStyles("intProp", null));
verify(mUpdatesReceiverMock).onIntSetterCalled(0);
verifyNoMoreInteractions(mUpdatesReceiverMock);
reset(mUpdatesReceiverMock);
mViewManager.updateProperties(null, buildStyles("intPropWithDefault", -1));
verify(mUpdatesReceiverMock).onIntSetterCalled(-1);
verifyNoMoreInteractions(mUpdatesReceiverMock);
reset(mUpdatesReceiverMock);
mViewManager.updateProperties(null, buildStyles("intPropWithDefault", null));
verify(mUpdatesReceiverMock).onIntSetterCalled(7168);
verifyNoMoreInteractions(mUpdatesReceiverMock);
reset(mUpdatesReceiverMock);
}
@Test
public void testDoubleSetter() {
mViewManager.updateProperties(null, buildStyles("doubleProp", 13.0));
verify(mUpdatesReceiverMock).onDoubleSetterCalled(13.0);
verifyNoMoreInteractions(mUpdatesReceiverMock);
reset(mUpdatesReceiverMock);
mViewManager.updateProperties(null, buildStyles("doubleProp", null));
verify(mUpdatesReceiverMock).onDoubleSetterCalled(0.0);
verifyNoMoreInteractions(mUpdatesReceiverMock);
reset(mUpdatesReceiverMock);
mViewManager.updateProperties(null, buildStyles("doublePropWithDefault", -1.0));
verify(mUpdatesReceiverMock).onDoubleSetterCalled(-1.0);
verifyNoMoreInteractions(mUpdatesReceiverMock);
reset(mUpdatesReceiverMock);
mViewManager.updateProperties(null, buildStyles("doublePropWithDefault", null));
verify(mUpdatesReceiverMock).onDoubleSetterCalled(-88.0);
verifyNoMoreInteractions(mUpdatesReceiverMock);
reset(mUpdatesReceiverMock);
}
@Test
public void testFloatSetter() {
mViewManager.updateProperties(null, buildStyles("floatProp", 13.0));
verify(mUpdatesReceiverMock).onFloatSetterCalled(13.0f);
verifyNoMoreInteractions(mUpdatesReceiverMock);
reset(mUpdatesReceiverMock);
mViewManager.updateProperties(null, buildStyles("floatProp", null));
verify(mUpdatesReceiverMock).onFloatSetterCalled(0.0f);
verifyNoMoreInteractions(mUpdatesReceiverMock);
reset(mUpdatesReceiverMock);
mViewManager.updateProperties(null, buildStyles("floatPropWithDefault", -1.0));
verify(mUpdatesReceiverMock).onFloatSetterCalled(-1.0f);
verifyNoMoreInteractions(mUpdatesReceiverMock);
reset(mUpdatesReceiverMock);
mViewManager.updateProperties(null, buildStyles("floatPropWithDefault", null));
verify(mUpdatesReceiverMock).onFloatSetterCalled(14.0f);
verifyNoMoreInteractions(mUpdatesReceiverMock);
reset(mUpdatesReceiverMock);
}
@Test
public void testStringSetter() {
mViewManager.updateProperties(null, buildStyles("stringProp", "someRandomString"));
verify(mUpdatesReceiverMock).onStringSetterCalled("someRandomString");
verifyNoMoreInteractions(mUpdatesReceiverMock);
reset(mUpdatesReceiverMock);
mViewManager.updateProperties(null, buildStyles("stringProp", null));
verify(mUpdatesReceiverMock).onStringSetterCalled(null);
verifyNoMoreInteractions(mUpdatesReceiverMock);
reset(mUpdatesReceiverMock);
}
@Test
public void testBoxedBooleanSetter() {
mViewManager.updateProperties(null, buildStyles("boxedBoolProp", true));
verify(mUpdatesReceiverMock).onBoxedBooleanSetterCalled(Boolean.TRUE);
verifyNoMoreInteractions(mUpdatesReceiverMock);
reset(mUpdatesReceiverMock);
mViewManager.updateProperties(null, buildStyles("boxedBoolProp", false));
verify(mUpdatesReceiverMock).onBoxedBooleanSetterCalled(Boolean.FALSE);
verifyNoMoreInteractions(mUpdatesReceiverMock);
reset(mUpdatesReceiverMock);
mViewManager.updateProperties(null, buildStyles("boxedBoolProp", null));
verify(mUpdatesReceiverMock).onBoxedBooleanSetterCalled(null);
verifyNoMoreInteractions(mUpdatesReceiverMock);
reset(mUpdatesReceiverMock);
}
@Test
public void testBoxedIntSetter() {
mViewManager.updateProperties(null, buildStyles("boxedIntProp", 55));
verify(mUpdatesReceiverMock).onBoxedIntSetterCalled(Integer.valueOf(55));
verifyNoMoreInteractions(mUpdatesReceiverMock);
reset(mUpdatesReceiverMock);
mViewManager.updateProperties(null, buildStyles("boxedIntProp", null));
verify(mUpdatesReceiverMock).onBoxedIntSetterCalled(null);
verifyNoMoreInteractions(mUpdatesReceiverMock);
reset(mUpdatesReceiverMock);
}
@Test
public void testArraySetter() {
ReadableArray array = new JavaOnlyArray();
mViewManager.updateProperties(null, buildStyles("arrayProp", array));
verify(mUpdatesReceiverMock).onArraySetterCalled(array);
verifyNoMoreInteractions(mUpdatesReceiverMock);
reset(mUpdatesReceiverMock);
mViewManager.updateProperties(null, buildStyles("arrayProp", null));
verify(mUpdatesReceiverMock).onArraySetterCalled(null);
verifyNoMoreInteractions(mUpdatesReceiverMock);
reset(mUpdatesReceiverMock);
}
@Test
public void testMapSetter() {
ReadableMap map = new JavaOnlyMap();
mViewManager.updateProperties(null, buildStyles("mapProp", map));
verify(mUpdatesReceiverMock).onMapSetterCalled(map);
verifyNoMoreInteractions(mUpdatesReceiverMock);
reset(mUpdatesReceiverMock);
mViewManager.updateProperties(null, buildStyles("mapProp", null));
verify(mUpdatesReceiverMock).onMapSetterCalled(null);
verifyNoMoreInteractions(mUpdatesReceiverMock);
reset(mUpdatesReceiverMock);
}
@Test
public void testFloatGroupSetter() {
mViewManager.updateProperties(null, buildStyles("floatGroupPropFirst", 11.0));
verify(mUpdatesReceiverMock).onFloatGroupPropSetterCalled(0, 11.0f);
verifyNoMoreInteractions(mUpdatesReceiverMock);
reset(mUpdatesReceiverMock);
mViewManager.updateProperties(null, buildStyles("floatGroupPropSecond", -111.0));
verify(mUpdatesReceiverMock).onFloatGroupPropSetterCalled(1, -111.0f);
verifyNoMoreInteractions(mUpdatesReceiverMock);
reset(mUpdatesReceiverMock);
mViewManager.updateProperties(null, buildStyles("floatGroupPropSecond", null));
verify(mUpdatesReceiverMock).onFloatGroupPropSetterCalled(1, 0.0f);
verifyNoMoreInteractions(mUpdatesReceiverMock);
reset(mUpdatesReceiverMock);
mViewManager.updateProperties(null, buildStyles("floatGroupPropWithDefaultFirst", null));
verify(mUpdatesReceiverMock).onFloatGroupPropSetterCalled(0, -100.0f);
verifyNoMoreInteractions(mUpdatesReceiverMock);
reset(mUpdatesReceiverMock);
}
@Test
public void testIntGroupSetter() {
mViewManager.updateProperties(null, buildStyles("intGroupPropFirst", -7));
verify(mUpdatesReceiverMock).onIntGroupPropSetterCalled(0, -7);
verifyNoMoreInteractions(mUpdatesReceiverMock);
reset(mUpdatesReceiverMock);
mViewManager.updateProperties(null, buildStyles("intGroupPropSecond", -77));
verify(mUpdatesReceiverMock).onIntGroupPropSetterCalled(1, -77);
verifyNoMoreInteractions(mUpdatesReceiverMock);
reset(mUpdatesReceiverMock);
mViewManager.updateProperties(null, buildStyles("intGroupPropSecond", null));
verify(mUpdatesReceiverMock).onIntGroupPropSetterCalled(1, 0);
verifyNoMoreInteractions(mUpdatesReceiverMock);
reset(mUpdatesReceiverMock);
mViewManager.updateProperties(null, buildStyles("intGroupPropWithDefaultFirst", 5));
verify(mUpdatesReceiverMock).onIntGroupPropSetterCalled(0, 5);
verifyNoMoreInteractions(mUpdatesReceiverMock);
reset(mUpdatesReceiverMock);
mViewManager.updateProperties(null, buildStyles("intGroupPropWithDefaultFirst", null));
verify(mUpdatesReceiverMock).onIntGroupPropSetterCalled(0, 555);
verifyNoMoreInteractions(mUpdatesReceiverMock);
reset(mUpdatesReceiverMock);
mViewManager.updateProperties(null, buildStyles("intGroupPropWithDefaultSecond", null));
verify(mUpdatesReceiverMock).onIntGroupPropSetterCalled(1, 555);
verifyNoMoreInteractions(mUpdatesReceiverMock);
reset(mUpdatesReceiverMock);
}
@Test
public void testStringGroupSetter() {
mViewManager.updateProperties(null, buildStyles("boxedIntGroupPropFirst", -7));
verify(mUpdatesReceiverMock).onBoxedIntGroupPropSetterCalled(0, -7);
verifyNoMoreInteractions(mUpdatesReceiverMock);
reset(mUpdatesReceiverMock);
mViewManager.updateProperties(null, buildStyles("boxedIntGroupPropSecond", 12345));
verify(mUpdatesReceiverMock).onBoxedIntGroupPropSetterCalled(1, 12345);
verifyNoMoreInteractions(mUpdatesReceiverMock);
reset(mUpdatesReceiverMock);
mViewManager.updateProperties(null, buildStyles("boxedIntGroupPropSecond", null));
verify(mUpdatesReceiverMock).onBoxedIntGroupPropSetterCalled(1, null);
verifyNoMoreInteractions(mUpdatesReceiverMock);
reset(mUpdatesReceiverMock);
}
@Test(expected = JSApplicationIllegalArgumentException.class)
public void testFailToUpdateBoolPropWithMap() {
mViewManager.updateProperties(null, buildStyles("boolProp", new JavaOnlyMap()));
}
@Test(expected = JSApplicationIllegalArgumentException.class)
public void testFailToUpdateStringPropWithDouble() {
mViewManager.updateProperties(null, buildStyles("stringProp", 14.5));
}
@Test(expected = JSApplicationIllegalArgumentException.class)
public void testFailToUpdateDoublePropWithString() {
mViewManager.updateProperties(null, buildStyles("doubleProp", "hello"));
}
@Test(expected = JSApplicationIllegalArgumentException.class)
public void testFailToUpdateIntPropWithDouble() {
mViewManager.updateProperties(null, buildStyles("intProp", -7.4));
}
@Test(expected = JSApplicationIllegalArgumentException.class)
public void testFailToUpdateArrayPropWithBool() {
mViewManager.updateProperties(null, buildStyles("arrayProp", false));
}
@Test(expected = JSApplicationIllegalArgumentException.class)
public void testFailToUpdateMapPropWithArray() {
mViewManager.updateProperties(null, buildStyles("mapProp", new JavaOnlyArray()));
}
@Test(expected = JSApplicationIllegalArgumentException.class)
public void testFailToUpdateBoxedIntPropWithBoxedDouble() {
mViewManager.updateProperties(null, buildStyles("boxedIntProp", Double.valueOf(1)));
}
}