/** * 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 javax.annotation.Nullable; import com.facebook.react.bridge.ReadableArray; import com.facebook.react.bridge.ReadableMap; 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.mockito.Mockito.mock; import static org.mockito.Mockito.reset; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verifyNoMoreInteractions; /** * Test {@link ReactProp} annotation for {@link ReactShadowNode}. More comprahensive test of this * annotation can be found in {@link ReactPropAnnotationSetterTest} where we test all possible types * of properties to be updated. */ @RunWith(RobolectricTestRunner.class) @PowerMockIgnore({"org.mockito.*", "org.robolectric.*", "android.*"}) public class ReactPropForShadowNodeSetterTest { @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); } public static ReactStylesDiffMap buildStyles(Object... keysAndValues) { return new ReactStylesDiffMap(JavaOnlyMap.of(keysAndValues)); } private class ShadowViewUnderTest extends ReactShadowNode { private ViewManagerUpdatesReceiver mViewManagerUpdatesReceiver; private ShadowViewUnderTest(ViewManagerUpdatesReceiver viewManagerUpdatesReceiver) { mViewManagerUpdatesReceiver = viewManagerUpdatesReceiver; } @ReactProp(name = "boolProp") public void setBoolProp(boolean value) { mViewManagerUpdatesReceiver.onBooleanSetterCalled(value); } @ReactProp(name = "stringProp") public void setStringProp(@Nullable String value) { mViewManagerUpdatesReceiver.onStringSetterCalled(value); } @ReactProp(name = "boxedIntProp") public void setBoxedIntProp(@Nullable Integer value) { mViewManagerUpdatesReceiver.onBoxedIntSetterCalled(value); } @ReactPropGroup(names = { "floatGroupPropFirst", "floatGroupPropSecond", }) public void setFloatGroupProp(int index, float value) { mViewManagerUpdatesReceiver.onFloatGroupPropSetterCalled(index, value); } } private ViewManagerUpdatesReceiver mUpdatesReceiverMock; private ShadowViewUnderTest mShadowView; @Before public void setup() { mUpdatesReceiverMock = mock(ViewManagerUpdatesReceiver.class); mShadowView = new ShadowViewUnderTest(mUpdatesReceiverMock); } @Test public void testBooleanSetter() { mShadowView.updateProperties(buildStyles("boolProp", true)); verify(mUpdatesReceiverMock).onBooleanSetterCalled(true); verifyNoMoreInteractions(mUpdatesReceiverMock); reset(mUpdatesReceiverMock); mShadowView.updateProperties(buildStyles("boolProp", false)); verify(mUpdatesReceiverMock).onBooleanSetterCalled(false); verifyNoMoreInteractions(mUpdatesReceiverMock); reset(mUpdatesReceiverMock); mShadowView.updateProperties(buildStyles("boolProp", null)); verify(mUpdatesReceiverMock).onBooleanSetterCalled(false); verifyNoMoreInteractions(mUpdatesReceiverMock); reset(mUpdatesReceiverMock); } @Test public void testStringSetter() { mShadowView.updateProperties(buildStyles("stringProp", "someRandomString")); verify(mUpdatesReceiverMock).onStringSetterCalled("someRandomString"); verifyNoMoreInteractions(mUpdatesReceiverMock); reset(mUpdatesReceiverMock); mShadowView.updateProperties(buildStyles("stringProp", null)); verify(mUpdatesReceiverMock).onStringSetterCalled(null); verifyNoMoreInteractions(mUpdatesReceiverMock); reset(mUpdatesReceiverMock); } @Test public void testFloatGroupSetter() { mShadowView.updateProperties(buildStyles("floatGroupPropFirst", 11.0)); verify(mUpdatesReceiverMock).onFloatGroupPropSetterCalled(0, 11.0f); verifyNoMoreInteractions(mUpdatesReceiverMock); reset(mUpdatesReceiverMock); mShadowView.updateProperties(buildStyles("floatGroupPropSecond", -111.0)); verify(mUpdatesReceiverMock).onFloatGroupPropSetterCalled(1, -111.0f); verifyNoMoreInteractions(mUpdatesReceiverMock); reset(mUpdatesReceiverMock); mShadowView.updateProperties(buildStyles("floatGroupPropSecond", null)); verify(mUpdatesReceiverMock).onFloatGroupPropSetterCalled(1, 0.0f); verifyNoMoreInteractions(mUpdatesReceiverMock); reset(mUpdatesReceiverMock); } }