Open sourced view tests
Reviewed By: mkonicek Differential Revision: D2881830 fb-gh-sync-id: fef9176964892c5aa40633c177f1d5d8e3aed499
This commit is contained in:
parent
ee30433b76
commit
33e8a03ada
|
@ -22,8 +22,18 @@ remote_file(
|
|||
sha1 = 'a944015ddf50fdad79302e42a85a351633c24472',
|
||||
)
|
||||
|
||||
android_library(
|
||||
name = 'imagepipeline',
|
||||
exported_deps = [
|
||||
':imagepipeline-core',
|
||||
':bolts',
|
||||
],
|
||||
visibility = ['//ReactAndroid/...',],
|
||||
)
|
||||
|
||||
|
||||
android_prebuilt_aar(
|
||||
name = 'imagepipeline',
|
||||
name = 'imagepipeline-core',
|
||||
aar = ':imagepipeline-aar',
|
||||
visibility = ['//ReactAndroid/...',],
|
||||
)
|
||||
|
@ -34,6 +44,18 @@ remote_file(
|
|||
sha1 = '93fe3e629c03aea8f63dabd80a0e616b0caef65b',
|
||||
)
|
||||
|
||||
prebuilt_jar(
|
||||
name = 'bolts',
|
||||
binary_jar = ':download-bolts',
|
||||
visibility = ['//ReactAndroid/...',],
|
||||
)
|
||||
|
||||
remote_file(
|
||||
name = 'download-bolts',
|
||||
url = 'mvn:com.parse.bolts:bolts-tasks:jar:1.4.0',
|
||||
sha1 = 'd85884acf6810a3bbbecb587f239005cbc846dc4',
|
||||
)
|
||||
|
||||
android_prebuilt_aar(
|
||||
name = 'fbcore',
|
||||
aar = ':fbcore-aar',
|
||||
|
|
|
@ -1,3 +1,14 @@
|
|||
include_defs('//ReactAndroid/DEFS')
|
||||
|
||||
android_library(
|
||||
name = 'jackson',
|
||||
exported_deps = [
|
||||
':databind',
|
||||
':annotations',
|
||||
],
|
||||
visibility = ['//ReactAndroid/...',],
|
||||
)
|
||||
|
||||
prebuilt_jar(
|
||||
name = 'core',
|
||||
binary_jar = ':jackson-core-binary-jar',
|
||||
|
@ -9,3 +20,27 @@ remote_file(
|
|||
url = 'mvn:com.fasterxml.jackson.core:jackson-core:jar:2.2.3',
|
||||
sha1 = '1a0113da2cab5f4c216b4e5e7c1dbfaa67087e14',
|
||||
)
|
||||
|
||||
prebuilt_jar(
|
||||
name = 'databind',
|
||||
binary_jar = ':jackson-databind-jar',
|
||||
visibility = ['//ReactAndroid/...',],
|
||||
)
|
||||
|
||||
remote_file(
|
||||
name = 'jackson-databind-jar',
|
||||
url = 'mvn:com.fasterxml.jackson.core:jackson-databind:jar:2.2.3',
|
||||
sha1 = '03ae380888029daefb91d3ecdca3a37d8cb92bc9',
|
||||
)
|
||||
|
||||
prebuilt_jar(
|
||||
name = 'annotations',
|
||||
binary_jar = ':jackson-annotations-jar',
|
||||
visibility = ['//ReactAndroid/...',],
|
||||
)
|
||||
|
||||
remote_file(
|
||||
name = 'jackson-annotations-jar',
|
||||
url = 'mvn:com.fasterxml.jackson.core:jackson-annotations:jar:2.2.3',
|
||||
sha1 = '0527fece4f23a457070a36c371a26d6c0208e1c3',
|
||||
)
|
||||
|
|
|
@ -0,0 +1,34 @@
|
|||
include_defs('//ReactAndroid/DEFS')
|
||||
|
||||
robolectric3_test(
|
||||
name = 'react',
|
||||
# Please change the contact to the oncall of your team
|
||||
contacts = ['oncall+fbandroid_sheriff@xmail.facebook.com'],
|
||||
srcs = glob(['*.java']),
|
||||
deps = [
|
||||
react_native_target('java/com/facebook/csslayout:csslayout'),
|
||||
react_native_target('java/com/facebook/react:react'),
|
||||
react_native_target('java/com/facebook/react/animation:animation'),
|
||||
react_native_target('java/com/facebook/react/bridge:bridge'),
|
||||
react_native_target('java/com/facebook/react/common:common'),
|
||||
react_native_target('java/com/facebook/react/touch:touch'),
|
||||
react_native_target('java/com/facebook/react/uimanager:uimanager'),
|
||||
react_native_target('java/com/facebook/react/views/text:text'),
|
||||
react_native_target('java/com/facebook/react/views/view:view'),
|
||||
react_native_tests_target('java/com/facebook/react/bridge:testhelpers'),
|
||||
|
||||
react_native_dep('third-party/java/robolectric3/robolectric:robolectric'),
|
||||
react_native_dep('third-party/java/fest:fest'),
|
||||
react_native_dep('third-party/java/junit:junit'),
|
||||
react_native_dep('third-party/java/okio:okio'),
|
||||
react_native_dep('third-party/java/mockito:mockito'),
|
||||
react_native_dep('third-party/java/okhttp:okhttp'),
|
||||
react_native_dep('third-party/java/jsr-305:jsr-305'),
|
||||
react_native_dep('libraries/fbcore/src/test/java/com/facebook/powermock:powermock'),
|
||||
],
|
||||
)
|
||||
|
||||
project_config(
|
||||
test_target = ':react',
|
||||
)
|
||||
|
|
@ -0,0 +1,218 @@
|
|||
/**
|
||||
* 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;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import com.facebook.react.bridge.JavaScriptModule;
|
||||
import com.facebook.react.bridge.NativeModule;
|
||||
import com.facebook.react.bridge.ReactApplicationContext;
|
||||
import com.facebook.react.uimanager.ViewManager;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.junit.Rule;
|
||||
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
import org.powermock.core.classloader.annotations.PowerMockIgnore;
|
||||
import org.powermock.modules.junit4.rule.PowerMockRule;
|
||||
import org.robolectric.RobolectricTestRunner;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
@RunWith(RobolectricTestRunner.class)
|
||||
@PowerMockIgnore({"org.mockito.*", "org.robolectric.*", "android.*"})
|
||||
public class CompositeReactPackageTest {
|
||||
|
||||
@Rule
|
||||
public PowerMockRule rule = new PowerMockRule();
|
||||
|
||||
@Mock ReactPackage packageNo1;
|
||||
@Mock ReactPackage packageNo2;
|
||||
@Mock ReactPackage packageNo3;
|
||||
|
||||
@Mock ReactApplicationContext reactContext;
|
||||
|
||||
@Before
|
||||
public void initMocks() {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testThatCreateNativeModulesIsCalledOnAllPackages() {
|
||||
// Given
|
||||
CompositeReactPackage composite = new CompositeReactPackage(packageNo1, packageNo2, packageNo3);
|
||||
|
||||
// When
|
||||
composite.createNativeModules(reactContext);
|
||||
|
||||
// Then
|
||||
verify(packageNo1).createNativeModules(reactContext);
|
||||
verify(packageNo2).createNativeModules(reactContext);
|
||||
verify(packageNo3).createNativeModules(reactContext);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testThatCreateJSModulesIsCalledOnAllPackages() {
|
||||
// Given
|
||||
CompositeReactPackage composite = new CompositeReactPackage(packageNo1, packageNo2, packageNo3);
|
||||
|
||||
// When
|
||||
composite.createJSModules();
|
||||
|
||||
// Then
|
||||
verify(packageNo1).createJSModules();
|
||||
verify(packageNo2).createJSModules();
|
||||
verify(packageNo3).createJSModules();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testThatCreateViewManagersIsCalledOnAllPackages() {
|
||||
// Given
|
||||
CompositeReactPackage composite = new CompositeReactPackage(packageNo1, packageNo2, packageNo3);
|
||||
|
||||
// When
|
||||
composite.createViewManagers(reactContext);
|
||||
|
||||
// Then
|
||||
verify(packageNo1).createViewManagers(reactContext);
|
||||
verify(packageNo2).createViewManagers(reactContext);
|
||||
verify(packageNo3).createViewManagers(reactContext);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testThatCompositeReturnsASumOfNativeModules() {
|
||||
// Given
|
||||
CompositeReactPackage composite = new CompositeReactPackage(packageNo1, packageNo2);
|
||||
|
||||
NativeModule moduleNo1 = mock(NativeModule.class);
|
||||
when(moduleNo1.getName()).thenReturn("ModuleNo1");
|
||||
|
||||
// module2 and module3 will share same name, composite should return only the latter one
|
||||
final String sameModuleName = "SameModuleName";
|
||||
|
||||
NativeModule moduleNo2 = mock(NativeModule.class);
|
||||
when(moduleNo2.getName()).thenReturn(sameModuleName);
|
||||
|
||||
NativeModule moduleNo3 = mock(NativeModule.class);
|
||||
when(moduleNo3.getName()).thenReturn(sameModuleName);
|
||||
|
||||
NativeModule moduleNo4 = mock(NativeModule.class);
|
||||
when(moduleNo4.getName()).thenReturn("ModuleNo4");
|
||||
|
||||
when(packageNo1.createNativeModules(reactContext)).thenReturn(
|
||||
Arrays.asList(new NativeModule[]{moduleNo1, moduleNo2}));
|
||||
|
||||
when(packageNo2.createNativeModules(reactContext)).thenReturn(
|
||||
Arrays.asList(new NativeModule[]{moduleNo3, moduleNo4}));
|
||||
|
||||
// When
|
||||
List<NativeModule> compositeModules = composite.createNativeModules(reactContext);
|
||||
|
||||
// Then
|
||||
|
||||
// Wrapping lists into sets to be order-independent.
|
||||
// Note that there should be no module2 returned.
|
||||
Set<NativeModule> expected = new HashSet<>(
|
||||
Arrays.asList(new NativeModule[]{moduleNo1, moduleNo3, moduleNo4}));
|
||||
Set<NativeModule> actual = new HashSet<>(compositeModules);
|
||||
|
||||
assertEquals(expected, actual);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testThatCompositeReturnsASumOfViewManagers() {
|
||||
// Given
|
||||
CompositeReactPackage composite = new CompositeReactPackage(packageNo1, packageNo2);
|
||||
|
||||
ViewManager managerNo1 = mock(ViewManager.class);
|
||||
when(managerNo1.getName()).thenReturn("ManagerNo1");
|
||||
|
||||
// managerNo2 and managerNo3 will share same name, composite should return only the latter one
|
||||
final String sameModuleName = "SameModuleName";
|
||||
|
||||
ViewManager managerNo2 = mock(ViewManager.class);
|
||||
when(managerNo2.getName()).thenReturn(sameModuleName);
|
||||
|
||||
ViewManager managerNo3 = mock(ViewManager.class);
|
||||
when(managerNo3.getName()).thenReturn(sameModuleName);
|
||||
|
||||
ViewManager managerNo4 = mock(ViewManager.class);
|
||||
when(managerNo4.getName()).thenReturn("ManagerNo4");
|
||||
|
||||
when(packageNo1.createViewManagers(reactContext)).thenReturn(
|
||||
Arrays.asList(new ViewManager[]{managerNo1, managerNo2}));
|
||||
|
||||
when(packageNo2.createViewManagers(reactContext)).thenReturn(
|
||||
Arrays.asList(new ViewManager[]{managerNo3, managerNo4}));
|
||||
|
||||
// When
|
||||
List<ViewManager> compositeModules = composite.createViewManagers(reactContext);
|
||||
|
||||
// Then
|
||||
|
||||
// Wrapping lists into sets to be order-independent.
|
||||
// Note that there should be no managerNo2 returned.
|
||||
Set<ViewManager> expected = new HashSet<>(
|
||||
Arrays.asList(new ViewManager[]{managerNo1, managerNo3, managerNo4})
|
||||
);
|
||||
Set<ViewManager> actual = new HashSet<>(compositeModules);
|
||||
|
||||
assertEquals(expected, actual);
|
||||
}
|
||||
|
||||
// public access level is required by Mockito
|
||||
public static class JavaScriptModuleNo1 implements JavaScriptModule {};
|
||||
public static class JavaScriptModuleNo2 implements JavaScriptModule {};
|
||||
public static class JavaScriptModuleNo3 implements JavaScriptModule {};
|
||||
|
||||
@Test
|
||||
public void testThatCompositeReturnsASumOfJSModules() {
|
||||
// Given
|
||||
CompositeReactPackage composite = new CompositeReactPackage(packageNo1, packageNo2);
|
||||
|
||||
Class<? extends JavaScriptModule> moduleNo1 = mock(JavaScriptModuleNo1.class).getClass();
|
||||
Class<? extends JavaScriptModule> moduleNo2 = mock(JavaScriptModuleNo2.class).getClass();
|
||||
Class<? extends JavaScriptModule> moduleNo3 = mock(JavaScriptModuleNo3.class).getClass();
|
||||
|
||||
List<Class<? extends JavaScriptModule>> l1 = new ArrayList<>();
|
||||
l1.add(moduleNo1);
|
||||
when(packageNo1.createJSModules()).thenReturn(l1);
|
||||
|
||||
List<Class<? extends JavaScriptModule>> l2 = new ArrayList<>();
|
||||
l2.add(moduleNo2);
|
||||
l2.add(moduleNo3);
|
||||
when(packageNo2.createJSModules()).thenReturn(l2);
|
||||
|
||||
// When
|
||||
List<Class<? extends JavaScriptModule>> compositeModules = composite.createJSModules();
|
||||
|
||||
// Then
|
||||
|
||||
// wrapping lists into sets to be order-independent
|
||||
List<Class<? extends JavaScriptModule>> l3 = new ArrayList<>();
|
||||
l3.add(moduleNo1);
|
||||
l3.add(moduleNo2);
|
||||
l3.add(moduleNo3);
|
||||
Set<Class<? extends JavaScriptModule>> expected = new HashSet<>(l3);
|
||||
Set<Class<? extends JavaScriptModule>> actual = new HashSet<>(compositeModules);
|
||||
|
||||
assertEquals(expected, actual);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,192 @@
|
|||
/**
|
||||
* 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;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
import android.util.DisplayMetrics;
|
||||
import android.view.MotionEvent;
|
||||
|
||||
import com.facebook.react.bridge.Arguments;
|
||||
import com.facebook.react.bridge.ReactContext;
|
||||
import com.facebook.react.bridge.ReactApplicationContext;
|
||||
import com.facebook.react.bridge.CatalystInstance;
|
||||
import com.facebook.react.bridge.ReactTestHelper;
|
||||
import com.facebook.react.bridge.SimpleArray;
|
||||
import com.facebook.react.bridge.SimpleMap;
|
||||
import com.facebook.react.bridge.WritableArray;
|
||||
import com.facebook.react.uimanager.UIManagerModule;
|
||||
import com.facebook.react.uimanager.DisplayMetricsHolder;
|
||||
import com.facebook.react.uimanager.events.Event;
|
||||
import com.facebook.react.uimanager.events.EventDispatcher;
|
||||
import com.facebook.react.uimanager.events.RCTEventEmitter;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.junit.Rule;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
import org.mockito.invocation.InvocationOnMock;
|
||||
import org.mockito.stubbing.Answer;
|
||||
import org.powermock.api.mockito.PowerMockito;
|
||||
import org.powermock.core.classloader.annotations.PrepareForTest;
|
||||
import org.powermock.core.classloader.annotations.PowerMockIgnore;
|
||||
import org.powermock.modules.junit4.rule.PowerMockRule;
|
||||
import org.robolectric.RobolectricTestRunner;
|
||||
import org.robolectric.RuntimeEnvironment;
|
||||
|
||||
import static org.fest.assertions.api.Assertions.assertThat;
|
||||
import static org.mockito.Matchers.any;
|
||||
import static org.mockito.Matchers.eq;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.reset;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.verifyNoMoreInteractions;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
@PrepareForTest(Arguments.class)
|
||||
@RunWith(RobolectricTestRunner.class)
|
||||
@PowerMockIgnore({"org.mockito.*", "org.robolectric.*", "android.*"})
|
||||
public class RootViewTest {
|
||||
|
||||
@Rule
|
||||
public PowerMockRule rule = new PowerMockRule();
|
||||
|
||||
private ReactContext mReactContext;
|
||||
private CatalystInstance mCatalystInstanceMock;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
PowerMockito.mockStatic(Arguments.class);
|
||||
PowerMockito.when(Arguments.createArray()).thenAnswer(new Answer<Object>() {
|
||||
@Override
|
||||
public Object answer(InvocationOnMock invocation) throws Throwable {
|
||||
return new SimpleArray();
|
||||
}
|
||||
});
|
||||
PowerMockito.when(Arguments.createMap()).thenAnswer(new Answer<Object>() {
|
||||
@Override
|
||||
public Object answer(InvocationOnMock invocation) throws Throwable {
|
||||
return new SimpleMap();
|
||||
}
|
||||
});
|
||||
|
||||
mCatalystInstanceMock = ReactTestHelper.createMockCatalystInstance();
|
||||
mReactContext = new ReactApplicationContext(RuntimeEnvironment.application);
|
||||
mReactContext.initializeWithInstance(mCatalystInstanceMock);
|
||||
DisplayMetrics displayMetrics = mReactContext.getResources().getDisplayMetrics();
|
||||
DisplayMetricsHolder.setDisplayMetrics(displayMetrics);
|
||||
|
||||
UIManagerModule uiManagerModuleMock = mock(UIManagerModule.class);
|
||||
when(mCatalystInstanceMock.getNativeModule(UIManagerModule.class))
|
||||
.thenReturn(uiManagerModuleMock);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTouchEmitter() {
|
||||
ReactInstanceManager instanceManager = mock(ReactInstanceManager.class);
|
||||
when(instanceManager.getCurrentReactContext()).thenReturn(mReactContext);
|
||||
|
||||
UIManagerModule uiManager = mock(UIManagerModule.class);
|
||||
EventDispatcher eventDispatcher = mock(EventDispatcher.class);
|
||||
RCTEventEmitter eventEmitterModuleMock = mock(RCTEventEmitter.class);
|
||||
when(mCatalystInstanceMock.getNativeModule(UIManagerModule.class))
|
||||
.thenReturn(uiManager);
|
||||
when(uiManager.getEventDispatcher()).thenReturn(eventDispatcher);
|
||||
|
||||
int rootViewId = 7;
|
||||
|
||||
ReactRootView rootView = new ReactRootView(mReactContext);
|
||||
rootView.setId(rootViewId);
|
||||
rootView.startReactApplication(instanceManager, "");
|
||||
rootView.simulateAttachForTesting();
|
||||
|
||||
long ts = new Date().getTime();
|
||||
|
||||
// Test ACTION_DOWN event
|
||||
rootView.onTouchEvent(
|
||||
MotionEvent.obtain(100, ts, MotionEvent.ACTION_DOWN, 0, 0, 0));
|
||||
|
||||
ArgumentCaptor<Event> downEventCaptor = ArgumentCaptor.forClass(Event.class);
|
||||
verify(eventDispatcher).dispatchEvent(downEventCaptor.capture());
|
||||
verifyNoMoreInteractions(eventDispatcher);
|
||||
|
||||
downEventCaptor.getValue().dispatch(eventEmitterModuleMock);
|
||||
|
||||
ArgumentCaptor<SimpleArray> downActionTouchesArgCaptor =
|
||||
ArgumentCaptor.forClass(SimpleArray.class);
|
||||
verify(eventEmitterModuleMock).receiveTouches(
|
||||
eq("topTouchStart"),
|
||||
downActionTouchesArgCaptor.capture(),
|
||||
any(SimpleArray.class));
|
||||
verifyNoMoreInteractions(eventEmitterModuleMock);
|
||||
|
||||
assertThat(downActionTouchesArgCaptor.getValue().size()).isEqualTo(1);
|
||||
assertThat(downActionTouchesArgCaptor.getValue().getMap(0)).isEqualTo(
|
||||
SimpleMap.of(
|
||||
"pageX",
|
||||
0.,
|
||||
"pageY",
|
||||
0.,
|
||||
"locationX",
|
||||
0.,
|
||||
"locationY",
|
||||
0.,
|
||||
"target",
|
||||
rootViewId,
|
||||
"timeStamp",
|
||||
(double) ts,
|
||||
"identifier",
|
||||
0.));
|
||||
|
||||
// Test ACTION_UP event
|
||||
reset(eventEmitterModuleMock, eventDispatcher);
|
||||
|
||||
ArgumentCaptor<Event> upEventCaptor = ArgumentCaptor.forClass(Event.class);
|
||||
ArgumentCaptor<SimpleArray> upActionTouchesArgCaptor =
|
||||
ArgumentCaptor.forClass(SimpleArray.class);
|
||||
|
||||
rootView.onTouchEvent(
|
||||
MotionEvent.obtain(50, ts, MotionEvent.ACTION_UP, 0, 0, 0));
|
||||
verify(eventDispatcher).dispatchEvent(upEventCaptor.capture());
|
||||
verifyNoMoreInteractions(eventDispatcher);
|
||||
|
||||
upEventCaptor.getValue().dispatch(eventEmitterModuleMock);
|
||||
verify(eventEmitterModuleMock).receiveTouches(
|
||||
eq("topTouchEnd"),
|
||||
upActionTouchesArgCaptor.capture(),
|
||||
any(WritableArray.class));
|
||||
verifyNoMoreInteractions(eventEmitterModuleMock);
|
||||
|
||||
assertThat(upActionTouchesArgCaptor.getValue().size()).isEqualTo(1);
|
||||
assertThat(upActionTouchesArgCaptor.getValue().getMap(0)).isEqualTo(
|
||||
SimpleMap.of(
|
||||
"pageX",
|
||||
0.,
|
||||
"pageY",
|
||||
0.,
|
||||
"locationX",
|
||||
0.,
|
||||
"locationY",
|
||||
0.,
|
||||
"target",
|
||||
rootViewId,
|
||||
"timeStamp",
|
||||
(double) ts,
|
||||
"identifier",
|
||||
0.));
|
||||
|
||||
// Test other action
|
||||
reset(eventDispatcher);
|
||||
rootView.onTouchEvent(
|
||||
MotionEvent.obtain(50, new Date().getTime(), MotionEvent.ACTION_HOVER_MOVE, 0, 0, 0));
|
||||
verifyNoMoreInteractions(eventDispatcher);
|
||||
}
|
||||
}
|
|
@ -1,12 +1,12 @@
|
|||
include_defs('//ReactAndroid/DEFS')
|
||||
|
||||
STANDARD_TEST_SRCS = [
|
||||
'**/*Test.java',
|
||||
'*Test.java',
|
||||
]
|
||||
|
||||
android_library(
|
||||
name = 'testhelpers',
|
||||
srcs = glob(['**/*.java'], excludes = STANDARD_TEST_SRCS),
|
||||
srcs = glob(['*.java'], excludes = STANDARD_TEST_SRCS),
|
||||
deps = [
|
||||
react_native_target('java/com/facebook/react/bridge:bridge'),
|
||||
react_native_target('java/com/facebook/react/uimanager:uimanager'),
|
||||
|
@ -18,3 +18,32 @@ android_library(
|
|||
'PUBLIC'
|
||||
],
|
||||
)
|
||||
|
||||
robolectric3_test(
|
||||
name = 'bridge',
|
||||
# Please change the contact to the oncall of your team
|
||||
contacts = ['oncall+fbandroid_sheriff@xmail.facebook.com'],
|
||||
srcs = glob(STANDARD_TEST_SRCS),
|
||||
deps = [
|
||||
':testhelpers',
|
||||
react_native_target('java/com/facebook/react/bridge:bridge'),
|
||||
react_native_target('java/com/facebook/react/common:common'),
|
||||
react_native_target('java/com/facebook/react/uimanager:uimanager'),
|
||||
|
||||
react_native_dep('third-party/java/robolectric3/robolectric:robolectric'),
|
||||
react_native_dep('third-party/java/fest:fest'),
|
||||
react_native_dep('third-party/java/junit:junit'),
|
||||
react_native_dep('third-party/java/mockito:mockito'),
|
||||
react_native_dep('third-party/java/jackson:core'),
|
||||
react_native_dep('third-party/java/jackson:jackson'),
|
||||
react_native_dep('third-party/java/jsr-305:jsr-305'),
|
||||
react_native_dep('libraries/fbcore/src/test/java/com/facebook/powermock:powermock'),
|
||||
],
|
||||
visibility = [
|
||||
'PUBLIC'
|
||||
],
|
||||
)
|
||||
|
||||
project_config(
|
||||
test_target = ':bridge',
|
||||
)
|
||||
|
|
|
@ -0,0 +1,98 @@
|
|||
/**
|
||||
* 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.bridge;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.StringWriter;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonFactory;
|
||||
import com.fasterxml.jackson.core.JsonGenerator;
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.fest.assertions.api.Assertions.assertThat;
|
||||
|
||||
public class JavaScriptModuleConfigTest {
|
||||
|
||||
private static interface SomeModule extends JavaScriptModule {
|
||||
public void stringMethod(String arg);
|
||||
public void intMethod(int arg);
|
||||
}
|
||||
|
||||
private static interface OtherModule extends JavaScriptModule {
|
||||
public void method(String arg1, int arg2);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testModuleWithMethods() throws Exception {
|
||||
JavaScriptModulesConfig jsModulesConfig = new JavaScriptModulesConfig.Builder()
|
||||
.add(SomeModule.class)
|
||||
.build();
|
||||
|
||||
String json = getModuleDescriptions(jsModulesConfig);
|
||||
JsonNode node = parse(json);
|
||||
assertThat(node).hasSize(1);
|
||||
|
||||
JsonNode module = node.fields().next().getValue();
|
||||
assertThat(module).isNotNull();
|
||||
|
||||
JsonNode methods = module.get("methods");
|
||||
assertThat(methods)
|
||||
.isNotNull()
|
||||
.hasSize(2);
|
||||
|
||||
JsonNode intMethodNode = methods.get("intMethod");
|
||||
assertThat(intMethodNode).isNotNull();
|
||||
assertThat(intMethodNode.get("methodID").asInt()).isEqualTo(0);
|
||||
|
||||
JsonNode stringMethod = methods.get("stringMethod");
|
||||
assertThat(stringMethod).isNotNull();
|
||||
assertThat(stringMethod.get("methodID").asInt()).isEqualTo(1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMultipleModules() throws Exception {
|
||||
JavaScriptModulesConfig jsModulesConfig = new JavaScriptModulesConfig.Builder()
|
||||
.add(OtherModule.class)
|
||||
.add(SomeModule.class)
|
||||
.build();
|
||||
|
||||
String json = getModuleDescriptions(jsModulesConfig);
|
||||
JsonNode node = parse(json);
|
||||
assertThat(node).hasSize(2);
|
||||
|
||||
JsonNode someModuleNode = node.get("SomeModule");
|
||||
assertThat(someModuleNode).isNotNull();
|
||||
int someModuleID = someModuleNode.get("moduleID").asInt();
|
||||
|
||||
JsonNode otherModuleNode = node.get("OtherModule");
|
||||
assertThat(otherModuleNode).isNotNull();
|
||||
int otherModuleID = otherModuleNode.get("moduleID").asInt();
|
||||
assertThat(otherModuleID)
|
||||
.isNotEqualTo(someModuleID);
|
||||
}
|
||||
|
||||
private static String getModuleDescriptions(JavaScriptModulesConfig jsModulesConfig)
|
||||
throws IOException {
|
||||
JsonFactory jsonFactory = new JsonFactory();
|
||||
StringWriter writer = new StringWriter();
|
||||
JsonGenerator jg = jsonFactory.createGenerator(writer);
|
||||
jsModulesConfig.writeModuleDescriptions(jg);
|
||||
jg.close();
|
||||
return writer.getBuffer().toString();
|
||||
}
|
||||
|
||||
private JsonNode parse(String json) throws Exception {
|
||||
ObjectMapper mapper = new ObjectMapper();
|
||||
return mapper.readTree(json);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,296 @@
|
|||
/**
|
||||
* 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.bridge;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.StringWriter;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import com.facebook.react.common.MapBuilder;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonFactory;
|
||||
import com.fasterxml.jackson.core.JsonGenerator;
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.fasterxml.jackson.databind.node.TextNode;
|
||||
import org.junit.Test;
|
||||
import org.junit.Rule;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.powermock.modules.junit4.rule.PowerMockRule;
|
||||
import org.powermock.core.classloader.annotations.PowerMockIgnore;
|
||||
import org.robolectric.RobolectricTestRunner;
|
||||
|
||||
import static org.fest.assertions.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* Tests for {@link NativeModuleRegistry}.
|
||||
*/
|
||||
@RunWith(RobolectricTestRunner.class)
|
||||
@PowerMockIgnore({"org.mockito.*", "org.robolectric.*", "android.*"})
|
||||
public class NativeModuleRegistryTest {
|
||||
|
||||
@Rule
|
||||
public PowerMockRule rule = new PowerMockRule();
|
||||
|
||||
@Test
|
||||
public void testModuleWithMethods() throws Exception {
|
||||
NativeModuleRegistry registry = new NativeModuleRegistry.Builder()
|
||||
.add(new MethodsModule())
|
||||
.build();
|
||||
|
||||
String json = getModuleDescriptions(registry);
|
||||
JsonNode node = parse(json);
|
||||
|
||||
JsonNode module = node.fields().next().getValue();
|
||||
assertThat(module).isNotNull();
|
||||
|
||||
JsonNode methods = module.get("methods");
|
||||
assertThat(methods).isNotNull();
|
||||
|
||||
ArrayList<String> expected = new ArrayList<String>();
|
||||
expected.add("doSomething");
|
||||
expected.add("saveData");
|
||||
|
||||
assertMethodsContainExactly(methods, expected);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAsyncMethod() throws Exception {
|
||||
NativeModuleRegistry registry = new NativeModuleRegistry.Builder()
|
||||
.add(new MethodsModule())
|
||||
.build();
|
||||
|
||||
String json = getModuleDescriptions(registry);
|
||||
JsonNode node = parse(json);
|
||||
|
||||
JsonNode asyncMethodData = node.get("TestModule").get("methods").get("saveData");
|
||||
assertThat(asyncMethodData.get("type")).isEqualTo(new TextNode("remoteAsync"));
|
||||
|
||||
JsonNode regularMethodData = node.get("TestModule").get("methods").get("doSomething");
|
||||
assertThat(regularMethodData.get("type")).isNotEqualTo(new TextNode("remoteAsync"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testModuleWithConstants() throws Exception {
|
||||
ConstantsModule constantsModule = new ConstantsModule();
|
||||
NativeModuleRegistry registry = new NativeModuleRegistry.Builder()
|
||||
.add(constantsModule)
|
||||
.build();
|
||||
|
||||
String json = getModuleDescriptions(registry);
|
||||
JsonNode node = parse(json);
|
||||
|
||||
JsonNode module = node.fields().next().getValue();
|
||||
assertThat(module).isNotNull();
|
||||
|
||||
JsonNode methods = module.get("methods");
|
||||
assertThat(methods).isNotNull();
|
||||
|
||||
ArrayList<String> expected = new ArrayList<String>();
|
||||
expected.add("runDMC");
|
||||
|
||||
assertMethodsContainExactly(methods, expected);
|
||||
|
||||
JsonNode constants = module.get("constants");
|
||||
assertThat(constants.get("testInt").asInt()).isEqualTo(3);
|
||||
assertThat(constants.get("testDouble").asDouble()).isEqualTo(3.14);
|
||||
assertThat(constants.get("testString").asText()).isEqualTo("red panda");
|
||||
|
||||
JsonNode stringMap = constants.get("testStringMap");
|
||||
assertThat(stringMap.get("war_room").asText()).isEqualTo("17.1");
|
||||
assertThat(stringMap.get("android_corex").asText()).isEqualTo("16.1");
|
||||
|
||||
JsonNode intMap = constants.get("testIntMap");
|
||||
assertThat(intMap.get("42").asInt()).isEqualTo(1);
|
||||
assertThat(intMap.get("84").asInt()).isEqualTo(2);
|
||||
|
||||
JsonNode stringList = constants.get("testStringList");
|
||||
assertThat(stringList.get(0).asText()).isEqualTo("vulpes vulpes");
|
||||
assertThat(stringList.get(4).asText()).isEqualTo("vulpes velox");
|
||||
|
||||
JsonNode intList = constants.get("testIntList");
|
||||
assertThat(intList.get(0).asInt()).isEqualTo(3);
|
||||
assertThat(intList.get(4).asInt()).isEqualTo(5);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testModuleWithOnlyConstants() throws Exception {
|
||||
OnlyConstantsModule onlyConstantsModule = new OnlyConstantsModule();
|
||||
NativeModuleRegistry registry = new NativeModuleRegistry.Builder()
|
||||
.add(onlyConstantsModule)
|
||||
.build();
|
||||
|
||||
String json = getModuleDescriptions(registry);
|
||||
JsonNode node = parse(json);
|
||||
|
||||
JsonNode module = node.fields().next().getValue();
|
||||
assertThat(module).isNotNull();
|
||||
|
||||
JsonNode constants = module.get("constants");
|
||||
assertThat(constants.get("testInt").asInt()).isEqualTo(4);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testModuleWithNestedMapConstants() throws Exception {
|
||||
NestedMapConstantsModule nestedMapConstantsModule = new NestedMapConstantsModule();
|
||||
NativeModuleRegistry registry = new NativeModuleRegistry.Builder()
|
||||
.add(nestedMapConstantsModule)
|
||||
.build();
|
||||
|
||||
String json = getModuleDescriptions(registry);
|
||||
JsonNode node = parse(json);
|
||||
|
||||
JsonNode module = node.fields().next().getValue();
|
||||
assertThat(module).isNotNull();
|
||||
|
||||
JsonNode constants = module.get("constants");
|
||||
assertThat(constants).isNotNull();
|
||||
|
||||
JsonNode nestedMapConstant = constants.get("nestedMap");
|
||||
assertThat(nestedMapConstant).isNotNull();
|
||||
|
||||
JsonNode firstLevel = nestedMapConstant.get("weNeedToGoDeeper");
|
||||
assertThat(firstLevel).isNotNull();
|
||||
|
||||
JsonNode secondLevel = firstLevel.get("evenDeeper");
|
||||
assertThat(secondLevel).isNotNull();
|
||||
|
||||
assertThat(secondLevel.get("inception").asBoolean()).isTrue();
|
||||
}
|
||||
|
||||
private JsonNode parse(String json) throws Exception {
|
||||
ObjectMapper mapper = new ObjectMapper();
|
||||
return mapper.readTree(json);
|
||||
}
|
||||
|
||||
private void assertMethodsContainExactly(JsonNode methodsObject, List<String> methodNames) {
|
||||
ArrayList<String> actual = new ArrayList();
|
||||
Iterator<Map.Entry<String,JsonNode>> fields = methodsObject.fields();
|
||||
while (fields.hasNext()) {
|
||||
String name = fields.next().getKey();
|
||||
actual.add(name);
|
||||
}
|
||||
assertThat(actual)
|
||||
.hasSize(methodNames.size())
|
||||
.containsAll(methodNames);
|
||||
}
|
||||
|
||||
private static String getModuleDescriptions(NativeModuleRegistry registry)
|
||||
throws IOException {
|
||||
JsonFactory jsonFactory = new JsonFactory();
|
||||
StringWriter writer = new StringWriter();
|
||||
JsonGenerator jg = jsonFactory.createGenerator(writer);
|
||||
registry.writeModuleDescriptions(jg);
|
||||
jg.close();
|
||||
return writer.getBuffer().toString();
|
||||
}
|
||||
|
||||
private static class MethodsModule extends BaseJavaModule {
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "TestModule";
|
||||
}
|
||||
|
||||
public void notACatalystMethod() {
|
||||
}
|
||||
|
||||
@ReactMethod
|
||||
public void doSomething() {
|
||||
}
|
||||
|
||||
@ReactMethod
|
||||
public void saveData(Promise promise) {
|
||||
}
|
||||
}
|
||||
|
||||
private static class ConstantsModule extends BaseJavaModule {
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "ConstantsModule";
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Object> getConstants() {
|
||||
HashMap<String, Object> constants = new HashMap<String, Object>();
|
||||
constants.put("testInt", 3);
|
||||
constants.put("testDouble", 3.14);
|
||||
constants.put("testString", "red panda");
|
||||
constants.put(
|
||||
"testStringMap",
|
||||
MapBuilder.of(
|
||||
"war_room",
|
||||
"17.1",
|
||||
"android_corex",
|
||||
"16.1"));
|
||||
constants.put(
|
||||
"testIntMap",
|
||||
MapBuilder.of(
|
||||
42,
|
||||
1,
|
||||
84,
|
||||
2));
|
||||
constants.put(
|
||||
"testStringList",
|
||||
Arrays.asList(
|
||||
new String[]{
|
||||
"vulpes vulpes",
|
||||
"vulpes cana",
|
||||
"vulpes chama",
|
||||
"vulpes fulfa",
|
||||
"vulpes velox"}));
|
||||
constants.put("testIntList", Arrays.asList(3, 1, 4, 1, 5));
|
||||
return constants;
|
||||
}
|
||||
|
||||
@ReactMethod
|
||||
public void runDMC() {
|
||||
}
|
||||
}
|
||||
|
||||
private static class OnlyConstantsModule extends BaseJavaModule {
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "OnlyConstantsModule";
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Object> getConstants() {
|
||||
return MapBuilder.<String, Object>of("testInt", 4);
|
||||
}
|
||||
}
|
||||
|
||||
private static class NestedMapConstantsModule extends BaseJavaModule {
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "NestedMapConstantsModule";
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Object> getConstants() {
|
||||
return MapBuilder.<String, Object>of(
|
||||
"nestedMap",
|
||||
MapBuilder.of(
|
||||
"weNeedToGoDeeper",
|
||||
MapBuilder.of(
|
||||
"evenDeeper",
|
||||
MapBuilder.of("inception", true))));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,39 @@
|
|||
include_defs('//ReactAndroid/DEFS')
|
||||
|
||||
robolectric3_test(
|
||||
name = 'views',
|
||||
# Please change the contact to the oncall of your team
|
||||
contacts = ['oncall+fbandroid_sheriff@xmail.facebook.com'],
|
||||
srcs = glob(['**/*.java']),
|
||||
deps = [
|
||||
react_native_target('java/com/facebook/csslayout:csslayout'),
|
||||
react_native_target('java/com/facebook/react:react'),
|
||||
react_native_target('java/com/facebook/react/bridge:bridge'),
|
||||
react_native_target('java/com/facebook/react/common:common'),
|
||||
react_native_target('java/com/facebook/react/touch:touch'),
|
||||
react_native_target('java/com/facebook/react/uimanager:uimanager'),
|
||||
react_native_target('java/com/facebook/react/uimanager/annotations:annotations'),
|
||||
react_native_target('java/com/facebook/react/views/image:image'),
|
||||
react_native_target('java/com/facebook/react/views/text:text'),
|
||||
react_native_target('java/com/facebook/react/views/textinput:textinput'),
|
||||
react_native_target('java/com/facebook/react/views/view:view'),
|
||||
|
||||
react_native_tests_target('java/com/facebook/react/bridge:testhelpers'),
|
||||
react_native_dep('third-party/java/robolectric3/robolectric:robolectric'),
|
||||
react_native_dep('third-party/java/fest:fest'),
|
||||
react_native_dep('third-party/java/junit:junit'),
|
||||
react_native_dep('third-party/java/okio:okio'),
|
||||
react_native_dep('third-party/java/mockito:mockito'),
|
||||
react_native_dep('third-party/java/okhttp:okhttp'),
|
||||
react_native_dep('third-party/java/jsr-305:jsr-305'),
|
||||
|
||||
react_native_dep('libraries/fbcore/src/test/java/com/facebook/powermock:powermock'),
|
||||
react_native_dep('libraries/fresco/fresco-react-native:fresco-react-native'),
|
||||
react_native_dep('libraries/fresco/fresco-react-native:imagepipeline'),
|
||||
react_native_dep('libraries/fresco/fresco-react-native:fresco-drawee'),
|
||||
],
|
||||
)
|
||||
|
||||
project_config(
|
||||
test_target = ':views',
|
||||
)
|
|
@ -0,0 +1,49 @@
|
|||
/**
|
||||
* 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.views.image;
|
||||
|
||||
import com.facebook.drawee.drawable.ScalingUtils;
|
||||
|
||||
import org.junit.Rule;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.junit.Test;
|
||||
import org.powermock.core.classloader.annotations.PowerMockIgnore;
|
||||
import org.powermock.modules.junit4.rule.PowerMockRule;
|
||||
import org.robolectric.RobolectricTestRunner;
|
||||
import org.robolectric.RuntimeEnvironment;
|
||||
|
||||
import static org.fest.assertions.api.Assertions.assertThat;
|
||||
|
||||
@RunWith(RobolectricTestRunner.class)
|
||||
@PowerMockIgnore({"org.mockito.*", "org.robolectric.*", "android.*"})
|
||||
public class ImageResizeModeTest {
|
||||
|
||||
@Rule
|
||||
public PowerMockRule rule = new PowerMockRule();
|
||||
|
||||
@Test
|
||||
public void testImageResizeMode() {
|
||||
assertThat(ImageResizeMode.toScaleType(null))
|
||||
.isEqualTo(ScalingUtils.ScaleType.CENTER_CROP);
|
||||
|
||||
assertThat(ImageResizeMode.toScaleType("contain"))
|
||||
.isEqualTo(ScalingUtils.ScaleType.CENTER_INSIDE);
|
||||
|
||||
assertThat(ImageResizeMode.toScaleType("cover"))
|
||||
.isEqualTo(ScalingUtils.ScaleType.CENTER_CROP);
|
||||
|
||||
assertThat(ImageResizeMode.toScaleType("stretch"))
|
||||
.isEqualTo(ScalingUtils.ScaleType.FIT_XY);
|
||||
|
||||
// No resizeMode set
|
||||
assertThat(ImageResizeMode.defaultValue())
|
||||
.isEqualTo(ScalingUtils.ScaleType.CENTER_CROP);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,134 @@
|
|||
/**
|
||||
* 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.views.image;
|
||||
|
||||
import android.graphics.Color;
|
||||
import android.util.DisplayMetrics;
|
||||
|
||||
import com.facebook.drawee.backends.pipeline.Fresco;
|
||||
import com.facebook.react.bridge.CatalystInstance;
|
||||
import com.facebook.react.bridge.ReactTestHelper;
|
||||
import com.facebook.react.bridge.JSApplicationIllegalArgumentException;
|
||||
import com.facebook.react.bridge.ReactApplicationContext;
|
||||
import com.facebook.react.bridge.SimpleMap;
|
||||
import com.facebook.react.uimanager.ReactStylesDiffMap;
|
||||
import com.facebook.react.uimanager.DisplayMetricsHolder;
|
||||
import com.facebook.react.uimanager.ThemedReactContext;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.Rule;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.powermock.modules.junit4.rule.PowerMockRule;
|
||||
import org.powermock.core.classloader.annotations.PowerMockIgnore;
|
||||
import org.robolectric.RobolectricTestRunner;
|
||||
import org.robolectric.RuntimeEnvironment;
|
||||
import org.robolectric.Robolectric;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertNull;
|
||||
|
||||
/**
|
||||
* Verify that {@link ScalingUtils} properties are being applied correctly
|
||||
* by {@link ReactImageManager}.
|
||||
*/
|
||||
@RunWith(RobolectricTestRunner.class)
|
||||
@PowerMockIgnore({"org.mockito.*", "org.robolectric.*", "android.*"})
|
||||
public class ReactImagePropertyTest {
|
||||
|
||||
@Rule
|
||||
public PowerMockRule rule = new PowerMockRule();
|
||||
|
||||
private ReactApplicationContext mContext;
|
||||
private CatalystInstance mCatalystInstanceMock;
|
||||
private ThemedReactContext mThemeContext;
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
mContext = new ReactApplicationContext(RuntimeEnvironment.application);
|
||||
mCatalystInstanceMock = ReactTestHelper.createMockCatalystInstance();
|
||||
mContext.initializeWithInstance(mCatalystInstanceMock);
|
||||
mThemeContext = new ThemedReactContext(mContext, mContext);
|
||||
Fresco.initialize(mContext);
|
||||
DisplayMetricsHolder.setDisplayMetrics(new DisplayMetrics());
|
||||
}
|
||||
|
||||
@After
|
||||
public void teardown() {
|
||||
DisplayMetricsHolder.setDisplayMetrics(null);
|
||||
}
|
||||
|
||||
public ReactStylesDiffMap buildStyles(Object... keysAndValues) {
|
||||
return new ReactStylesDiffMap(SimpleMap.of(keysAndValues));
|
||||
}
|
||||
|
||||
@Test(expected=JSApplicationIllegalArgumentException.class)
|
||||
public void testImageInvalidResizeMode() {
|
||||
ReactImageManager viewManager = new ReactImageManager();
|
||||
ReactImageView view = viewManager.createViewInstance(mThemeContext);
|
||||
viewManager.updateProperties(view, buildStyles("resizeMode", "pancakes"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBorderColor() {
|
||||
ReactImageManager viewManager = new ReactImageManager();
|
||||
ReactImageView view = viewManager.createViewInstance(mThemeContext);
|
||||
viewManager.updateProperties(view, buildStyles("src", "http://mysite.com/mypic.jpg"));
|
||||
|
||||
viewManager.updateProperties(view, buildStyles("borderColor", Color.argb(0, 0, 255, 255)));
|
||||
int borderColor = view.getHierarchy().getRoundingParams().getBorderColor();
|
||||
assertEquals(0, Color.alpha(borderColor));
|
||||
assertEquals(0, Color.red(borderColor));
|
||||
assertEquals(255, Color.green(borderColor));
|
||||
assertEquals(255, Color.blue(borderColor));
|
||||
|
||||
viewManager.updateProperties(view, buildStyles("borderColor", Color.argb(0, 255, 50, 128)));
|
||||
borderColor = view.getHierarchy().getRoundingParams().getBorderColor();
|
||||
assertEquals(0, Color.alpha(borderColor));
|
||||
assertEquals(255, Color.red(borderColor));
|
||||
assertEquals(50, Color.green(borderColor));
|
||||
assertEquals(128, Color.blue(borderColor));
|
||||
|
||||
viewManager.updateProperties(view, buildStyles("borderColor", null));
|
||||
borderColor = view.getHierarchy().getRoundingParams().getBorderColor();
|
||||
assertEquals(0, Color.alpha(borderColor));
|
||||
assertEquals(0, Color.red(borderColor));
|
||||
assertEquals(0, Color.green(borderColor));
|
||||
assertEquals(0, Color.blue(borderColor));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRoundedCorners() {
|
||||
ReactImageManager viewManager = new ReactImageManager();
|
||||
ReactImageView view = viewManager.createViewInstance(mThemeContext);
|
||||
viewManager.updateProperties(view, buildStyles("src", "http://mysite.com/mypic.jpg"));
|
||||
|
||||
// We can't easily verify if rounded corner was honored or not, this tests simply verifies
|
||||
// we're not crashing..
|
||||
viewManager.updateProperties(view, buildStyles("borderRadius", (double) 10));
|
||||
viewManager.updateProperties(view, buildStyles("borderRadius", (double) 0));
|
||||
viewManager.updateProperties(view, buildStyles("borderRadius", null));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTintColor() {
|
||||
ReactImageManager viewManager = new ReactImageManager();
|
||||
ReactImageView view = viewManager.createViewInstance(mThemeContext);
|
||||
assertNull(view.getColorFilter());
|
||||
viewManager.updateProperties(view, buildStyles("tintColor", Color.argb(50, 0, 0, 255)));
|
||||
// Can't actually assert the specific color so this is the next best thing.
|
||||
// Does the color filter now exist?
|
||||
assertNotNull(view.getColorFilter());
|
||||
viewManager.updateProperties(view, buildStyles("tintColor", null));
|
||||
assertNull(view.getColorFilter());
|
||||
}
|
||||
}
|
|
@ -0,0 +1,386 @@
|
|||
/**
|
||||
* 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.views.text;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import android.annotation.TargetApi;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.Typeface;
|
||||
import android.graphics.drawable.ColorDrawable;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.os.Build;
|
||||
import android.text.Spanned;
|
||||
import android.text.TextUtils;
|
||||
import android.text.style.AbsoluteSizeSpan;
|
||||
import android.view.Choreographer;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.facebook.react.ReactRootView;
|
||||
import com.facebook.react.bridge.Arguments;
|
||||
import com.facebook.react.bridge.ReactTestHelper;
|
||||
import com.facebook.react.bridge.ReactApplicationContext;
|
||||
import com.facebook.react.bridge.SimpleArray;
|
||||
import com.facebook.react.bridge.SimpleMap;
|
||||
import com.facebook.react.uimanager.ReactChoreographer;
|
||||
import com.facebook.react.uimanager.UIImplementation;
|
||||
import com.facebook.react.uimanager.UIManagerModule;
|
||||
import com.facebook.react.uimanager.ViewManager;
|
||||
import com.facebook.react.uimanager.ViewProps;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.Rule;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.invocation.InvocationOnMock;
|
||||
import org.mockito.stubbing.Answer;
|
||||
import org.powermock.api.mockito.PowerMockito;
|
||||
import org.powermock.core.classloader.annotations.PowerMockIgnore;
|
||||
import org.powermock.core.classloader.annotations.PrepareForTest;
|
||||
import org.powermock.modules.junit4.rule.PowerMockRule;
|
||||
import org.robolectric.Robolectric;
|
||||
import org.robolectric.RobolectricTestRunner;
|
||||
import org.robolectric.RuntimeEnvironment;
|
||||
|
||||
import static org.fest.assertions.api.Assertions.assertThat;
|
||||
import static org.mockito.Matchers.any;
|
||||
import static org.mockito.Mockito.doAnswer;
|
||||
import static org.mockito.Mockito.mock;
|
||||
|
||||
/**
|
||||
* Tests for {@link UIManagerModule} specifically for React Text/RawText.
|
||||
*/
|
||||
@PrepareForTest({Arguments.class, ReactChoreographer.class})
|
||||
@RunWith(RobolectricTestRunner.class)
|
||||
@PowerMockIgnore({"org.mockito.*", "org.robolectric.*", "android.*"})
|
||||
public class ReactTextTest {
|
||||
|
||||
@Rule
|
||||
public PowerMockRule rule = new PowerMockRule();
|
||||
|
||||
private ArrayList<Choreographer.FrameCallback> mPendingChoreographerCallbacks;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
PowerMockito.mockStatic(Arguments.class, ReactChoreographer.class);
|
||||
|
||||
ReactChoreographer choreographerMock = mock(ReactChoreographer.class);
|
||||
PowerMockito.when(Arguments.createMap()).thenAnswer(new Answer<Object>() {
|
||||
@Override
|
||||
public Object answer(InvocationOnMock invocation) throws Throwable {
|
||||
return new SimpleMap();
|
||||
}
|
||||
});
|
||||
PowerMockito.when(ReactChoreographer.getInstance()).thenReturn(choreographerMock);
|
||||
|
||||
mPendingChoreographerCallbacks = new ArrayList<>();
|
||||
doAnswer(new Answer() {
|
||||
@Override
|
||||
public Object answer(InvocationOnMock invocation) throws Throwable {
|
||||
mPendingChoreographerCallbacks
|
||||
.add((Choreographer.FrameCallback) invocation.getArguments()[1]);
|
||||
return null;
|
||||
}
|
||||
}).when(choreographerMock).postFrameCallback(
|
||||
any(ReactChoreographer.CallbackType.class),
|
||||
any(Choreographer.FrameCallback.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFontSizeApplied() {
|
||||
UIManagerModule uiManager = getUIManagerModule();
|
||||
|
||||
ReactRootView rootView = createText(
|
||||
uiManager,
|
||||
SimpleMap.of(ViewProps.FONT_SIZE, 21.0),
|
||||
SimpleMap.of(ReactTextShadowNode.PROP_TEXT, "test text"));
|
||||
|
||||
AbsoluteSizeSpan sizeSpan = getSingleSpan(
|
||||
(TextView) rootView.getChildAt(0), AbsoluteSizeSpan.class);
|
||||
assertThat(sizeSpan.getSize()).isEqualTo(21);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBoldFontApplied() {
|
||||
UIManagerModule uiManager = getUIManagerModule();
|
||||
|
||||
ReactRootView rootView = createText(
|
||||
uiManager,
|
||||
SimpleMap.of(ViewProps.FONT_WEIGHT, "bold"),
|
||||
SimpleMap.of(ReactTextShadowNode.PROP_TEXT, "test text"));
|
||||
|
||||
CustomStyleSpan customStyleSpan =
|
||||
getSingleSpan((TextView)rootView.getChildAt(0), CustomStyleSpan.class);
|
||||
assertThat(customStyleSpan.getWeight() & Typeface.BOLD).isNotZero();
|
||||
assertThat(customStyleSpan.getStyle() & Typeface.ITALIC).isZero();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNumericBoldFontApplied() {
|
||||
UIManagerModule uiManager = getUIManagerModule();
|
||||
|
||||
ReactRootView rootView = createText(
|
||||
uiManager,
|
||||
SimpleMap.of(ViewProps.FONT_WEIGHT, "500"),
|
||||
SimpleMap.of(ReactTextShadowNode.PROP_TEXT, "test text"));
|
||||
|
||||
CustomStyleSpan customStyleSpan =
|
||||
getSingleSpan((TextView) rootView.getChildAt(0), CustomStyleSpan.class);
|
||||
assertThat(customStyleSpan.getWeight() & Typeface.BOLD).isNotZero();
|
||||
assertThat(customStyleSpan.getStyle() & Typeface.ITALIC).isZero();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testItalicFontApplied() {
|
||||
UIManagerModule uiManager = getUIManagerModule();
|
||||
|
||||
ReactRootView rootView = createText(
|
||||
uiManager,
|
||||
SimpleMap.of(ViewProps.FONT_STYLE, "italic"),
|
||||
SimpleMap.of(ReactTextShadowNode.PROP_TEXT, "test text"));
|
||||
|
||||
CustomStyleSpan customStyleSpan =
|
||||
getSingleSpan((TextView) rootView.getChildAt(0), CustomStyleSpan.class);
|
||||
assertThat(customStyleSpan.getStyle() & Typeface.ITALIC).isNotZero();
|
||||
assertThat(customStyleSpan.getWeight() & Typeface.BOLD).isZero();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBoldItalicFontApplied() {
|
||||
UIManagerModule uiManager = getUIManagerModule();
|
||||
|
||||
ReactRootView rootView = createText(
|
||||
uiManager,
|
||||
SimpleMap.of(ViewProps.FONT_WEIGHT, "bold", ViewProps.FONT_STYLE, "italic"),
|
||||
SimpleMap.of(ReactTextShadowNode.PROP_TEXT, "test text"));
|
||||
|
||||
CustomStyleSpan customStyleSpan =
|
||||
getSingleSpan((TextView) rootView.getChildAt(0), CustomStyleSpan.class);
|
||||
assertThat(customStyleSpan.getStyle() & Typeface.ITALIC).isNotZero();
|
||||
assertThat(customStyleSpan.getWeight() & Typeface.BOLD).isNotZero();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNormalFontWeightApplied() {
|
||||
UIManagerModule uiManager = getUIManagerModule();
|
||||
|
||||
ReactRootView rootView = createText(
|
||||
uiManager,
|
||||
SimpleMap.of(ViewProps.FONT_WEIGHT, "normal"),
|
||||
SimpleMap.of(ReactTextShadowNode.PROP_TEXT, "test text"));
|
||||
|
||||
CustomStyleSpan customStyleSpan =
|
||||
getSingleSpan((TextView) rootView.getChildAt(0), CustomStyleSpan.class);
|
||||
assertThat(customStyleSpan.getWeight() & Typeface.BOLD).isZero();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNumericNormalFontWeightApplied() {
|
||||
UIManagerModule uiManager = getUIManagerModule();
|
||||
|
||||
ReactRootView rootView = createText(
|
||||
uiManager,
|
||||
SimpleMap.of(ViewProps.FONT_WEIGHT, "200"),
|
||||
SimpleMap.of(ReactTextShadowNode.PROP_TEXT, "test text"));
|
||||
|
||||
CustomStyleSpan customStyleSpan =
|
||||
getSingleSpan((TextView) rootView.getChildAt(0), CustomStyleSpan.class);
|
||||
assertThat(customStyleSpan.getWeight() & Typeface.BOLD).isZero();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNormalFontStyleApplied() {
|
||||
UIManagerModule uiManager = getUIManagerModule();
|
||||
|
||||
ReactRootView rootView = createText(
|
||||
uiManager,
|
||||
SimpleMap.of(ViewProps.FONT_STYLE, "normal"),
|
||||
SimpleMap.of(ReactTextShadowNode.PROP_TEXT, "test text"));
|
||||
|
||||
CustomStyleSpan customStyleSpan =
|
||||
getSingleSpan((TextView) rootView.getChildAt(0), CustomStyleSpan.class);
|
||||
assertThat(customStyleSpan.getStyle() & Typeface.ITALIC).isZero();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFontFamilyStyleApplied() {
|
||||
UIManagerModule uiManager = getUIManagerModule();
|
||||
|
||||
ReactRootView rootView = createText(
|
||||
uiManager,
|
||||
SimpleMap.of(ViewProps.FONT_FAMILY, "sans-serif"),
|
||||
SimpleMap.of(ReactTextShadowNode.PROP_TEXT, "test text"));
|
||||
|
||||
CustomStyleSpan customStyleSpan =
|
||||
getSingleSpan((TextView) rootView.getChildAt(0), CustomStyleSpan.class);
|
||||
assertThat(customStyleSpan.getFontFamily()).isEqualTo("sans-serif");
|
||||
assertThat(customStyleSpan.getStyle() & Typeface.ITALIC).isZero();
|
||||
assertThat(customStyleSpan.getWeight() & Typeface.BOLD).isZero();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFontFamilyBoldStyleApplied() {
|
||||
UIManagerModule uiManager = getUIManagerModule();
|
||||
|
||||
ReactRootView rootView = createText(
|
||||
uiManager,
|
||||
SimpleMap.of(ViewProps.FONT_FAMILY, "sans-serif", ViewProps.FONT_WEIGHT, "bold"),
|
||||
SimpleMap.of(ReactTextShadowNode.PROP_TEXT, "test text"));
|
||||
|
||||
CustomStyleSpan customStyleSpan =
|
||||
getSingleSpan((TextView) rootView.getChildAt(0), CustomStyleSpan.class);
|
||||
assertThat(customStyleSpan.getFontFamily()).isEqualTo("sans-serif");
|
||||
assertThat(customStyleSpan.getStyle() & Typeface.ITALIC).isZero();
|
||||
assertThat(customStyleSpan.getWeight() & Typeface.BOLD).isNotZero();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFontFamilyItalicStyleApplied() {
|
||||
UIManagerModule uiManager = getUIManagerModule();
|
||||
|
||||
ReactRootView rootView = createText(
|
||||
uiManager,
|
||||
SimpleMap.of(ViewProps.FONT_FAMILY, "sans-serif", ViewProps.FONT_STYLE, "italic"),
|
||||
SimpleMap.of(ReactTextShadowNode.PROP_TEXT, "test text"));
|
||||
|
||||
CustomStyleSpan customStyleSpan =
|
||||
getSingleSpan((TextView) rootView.getChildAt(0), CustomStyleSpan.class);
|
||||
assertThat(customStyleSpan.getFontFamily()).isEqualTo("sans-serif");
|
||||
assertThat(customStyleSpan.getStyle() & Typeface.ITALIC).isNotZero();
|
||||
assertThat(customStyleSpan.getWeight() & Typeface.BOLD).isZero();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFontFamilyBoldItalicStyleApplied() {
|
||||
UIManagerModule uiManager = getUIManagerModule();
|
||||
|
||||
ReactRootView rootView = createText(
|
||||
uiManager,
|
||||
SimpleMap.of(
|
||||
ViewProps.FONT_FAMILY, "sans-serif",
|
||||
ViewProps.FONT_WEIGHT, "500",
|
||||
ViewProps.FONT_STYLE, "italic"),
|
||||
SimpleMap.of(ReactTextShadowNode.PROP_TEXT, "test text"));
|
||||
|
||||
CustomStyleSpan customStyleSpan =
|
||||
getSingleSpan((TextView) rootView.getChildAt(0), CustomStyleSpan.class);
|
||||
assertThat(customStyleSpan.getFontFamily()).isEqualTo("sans-serif");
|
||||
assertThat(customStyleSpan.getStyle() & Typeface.ITALIC).isNotZero();
|
||||
assertThat(customStyleSpan.getWeight() & Typeface.BOLD).isNotZero();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBackgroundColorStyleApplied() {
|
||||
UIManagerModule uiManager = getUIManagerModule();
|
||||
|
||||
ReactRootView rootView = createText(
|
||||
uiManager,
|
||||
SimpleMap.of(ViewProps.BACKGROUND_COLOR, Color.BLUE),
|
||||
SimpleMap.of(ReactTextShadowNode.PROP_TEXT, "test text"));
|
||||
|
||||
Drawable backgroundDrawable = ((TextView) rootView.getChildAt(0)).getBackground();
|
||||
assertThat(((ColorDrawable) backgroundDrawable).getColor()).isEqualTo(Color.BLUE);
|
||||
}
|
||||
|
||||
// JELLY_BEAN is needed for TextView#getMaxLines(), which is OK, because in the actual code we
|
||||
// only use TextView#setMaxLines() which exists since API Level 1.
|
||||
@TargetApi(Build.VERSION_CODES.JELLY_BEAN)
|
||||
@Test
|
||||
public void testMaxLinesApplied() {
|
||||
UIManagerModule uiManager = getUIManagerModule();
|
||||
|
||||
ReactRootView rootView = createText(
|
||||
uiManager,
|
||||
SimpleMap.of(ViewProps.NUMBER_OF_LINES, 2),
|
||||
SimpleMap.of(ReactTextShadowNode.PROP_TEXT, "test text"));
|
||||
|
||||
TextView textView = (TextView) rootView.getChildAt(0);
|
||||
assertThat(textView.getText().toString()).isEqualTo("test text");
|
||||
assertThat(textView.getMaxLines()).isEqualTo(2);
|
||||
assertThat(textView.getEllipsize()).isEqualTo(TextUtils.TruncateAt.END);
|
||||
}
|
||||
|
||||
/**
|
||||
* Make sure TextView has exactly one span and that span has given type.
|
||||
*/
|
||||
private static <TSPAN> TSPAN getSingleSpan(TextView textView, Class<TSPAN> spanClass) {
|
||||
Spanned text = (Spanned) textView.getText();
|
||||
TSPAN[] spans = text.getSpans(0, text.length(), spanClass);
|
||||
assertThat(spans).hasSize(1);
|
||||
return spans[0];
|
||||
}
|
||||
|
||||
private ReactRootView createText(
|
||||
UIManagerModule uiManager,
|
||||
SimpleMap textProps,
|
||||
SimpleMap rawTextProps) {
|
||||
ReactRootView rootView = new ReactRootView(RuntimeEnvironment.application);
|
||||
int rootTag = uiManager.addMeasuredRootView(rootView);
|
||||
int textTag = rootTag + 1;
|
||||
int rawTextTag = textTag + 1;
|
||||
|
||||
uiManager.createView(
|
||||
textTag,
|
||||
ReactTextViewManager.REACT_CLASS,
|
||||
rootTag,
|
||||
textProps);
|
||||
uiManager.createView(
|
||||
rawTextTag,
|
||||
ReactRawTextManager.REACT_CLASS,
|
||||
rootTag,
|
||||
rawTextProps);
|
||||
|
||||
uiManager.manageChildren(
|
||||
textTag,
|
||||
null,
|
||||
null,
|
||||
SimpleArray.of(rawTextTag),
|
||||
SimpleArray.of(0),
|
||||
null);
|
||||
|
||||
uiManager.manageChildren(
|
||||
rootTag,
|
||||
null,
|
||||
null,
|
||||
SimpleArray.of(textTag),
|
||||
SimpleArray.of(0),
|
||||
null);
|
||||
|
||||
uiManager.onBatchComplete();
|
||||
executePendingChoreographerCallbacks();
|
||||
return rootView;
|
||||
}
|
||||
|
||||
private void executePendingChoreographerCallbacks() {
|
||||
ArrayList<Choreographer.FrameCallback> callbacks =
|
||||
new ArrayList<>(mPendingChoreographerCallbacks);
|
||||
mPendingChoreographerCallbacks.clear();
|
||||
for (Choreographer.FrameCallback frameCallback : callbacks) {
|
||||
frameCallback.doFrame(0);
|
||||
}
|
||||
}
|
||||
|
||||
public UIManagerModule getUIManagerModule() {
|
||||
ReactApplicationContext reactContext = ReactTestHelper.createCatalystContextForTest();
|
||||
List<ViewManager> viewManagers = Arrays.asList(
|
||||
new ViewManager[] {
|
||||
new ReactTextViewManager(),
|
||||
new ReactRawTextManager(),
|
||||
});
|
||||
UIManagerModule uiManagerModule = new UIManagerModule(
|
||||
reactContext,
|
||||
viewManagers,
|
||||
new UIImplementation(reactContext, viewManagers));
|
||||
uiManagerModule.onHostResume();
|
||||
return uiManagerModule;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,314 @@
|
|||
/**
|
||||
* 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.views.textinput;
|
||||
|
||||
import android.content.res.ColorStateList;
|
||||
import android.graphics.Color;
|
||||
import android.text.InputType;
|
||||
import android.util.DisplayMetrics;
|
||||
import android.view.Gravity;
|
||||
import android.widget.EditText;
|
||||
|
||||
import com.facebook.react.bridge.CatalystInstance;
|
||||
import com.facebook.react.bridge.ReactTestHelper;
|
||||
import com.facebook.react.bridge.ReactApplicationContext;
|
||||
import com.facebook.react.bridge.JSApplicationCausedNativeException;
|
||||
import com.facebook.react.bridge.SimpleMap;
|
||||
import com.facebook.react.uimanager.ReactStylesDiffMap;
|
||||
import com.facebook.react.uimanager.DisplayMetricsHolder;
|
||||
import com.facebook.react.views.text.DefaultStyleValuesUtil;
|
||||
import com.facebook.react.uimanager.ThemedReactContext;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.Rule;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.robolectric.Robolectric;
|
||||
import org.robolectric.RobolectricTestRunner;
|
||||
import org.robolectric.RuntimeEnvironment;
|
||||
import org.powermock.modules.junit4.rule.PowerMockRule;
|
||||
import org.powermock.core.classloader.annotations.PowerMockIgnore;
|
||||
|
||||
import static org.fest.assertions.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* Verify {@link EditText} view property being applied properly by {@link ReactTextInputManager}
|
||||
*/
|
||||
@RunWith(RobolectricTestRunner.class)
|
||||
@PowerMockIgnore({"org.mockito.*", "org.robolectric.*", "android.*"})
|
||||
public class ReactTextInputPropertyTest {
|
||||
|
||||
@Rule
|
||||
public PowerMockRule rule = new PowerMockRule();
|
||||
|
||||
private ReactApplicationContext mContext;
|
||||
private CatalystInstance mCatalystInstanceMock;
|
||||
private ThemedReactContext mThemedContext;
|
||||
private ReactTextInputManager mManager;
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
mContext = new ReactApplicationContext(RuntimeEnvironment.application);
|
||||
mCatalystInstanceMock = ReactTestHelper.createMockCatalystInstance();
|
||||
mContext.initializeWithInstance(mCatalystInstanceMock);
|
||||
mThemedContext = new ThemedReactContext(mContext, mContext);
|
||||
mManager = new ReactTextInputManager();
|
||||
DisplayMetricsHolder.setDisplayMetrics(new DisplayMetrics());
|
||||
}
|
||||
|
||||
public ReactStylesDiffMap buildStyles(Object... keysAndValues) {
|
||||
return new ReactStylesDiffMap(SimpleMap.of(keysAndValues));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAutoCorrect() {
|
||||
ReactEditText view = mManager.createViewInstance(mThemedContext);
|
||||
|
||||
mManager.updateProperties(view, buildStyles());
|
||||
assertThat(view.getInputType() & InputType.TYPE_TEXT_FLAG_AUTO_CORRECT).isZero();
|
||||
assertThat(view.getInputType() & InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS).isZero();
|
||||
|
||||
mManager.updateProperties(view, buildStyles("autoCorrect", true));
|
||||
assertThat(view.getInputType() & InputType.TYPE_TEXT_FLAG_AUTO_CORRECT).isNotZero();
|
||||
assertThat(view.getInputType() & InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS).isZero();
|
||||
|
||||
mManager.updateProperties(view, buildStyles("autoCorrect", false));
|
||||
assertThat(view.getInputType() & InputType.TYPE_TEXT_FLAG_AUTO_CORRECT).isZero();
|
||||
assertThat(view.getInputType() & InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS).isNotZero();
|
||||
|
||||
mManager.updateProperties(view, buildStyles("autoCorrect", null));
|
||||
assertThat(view.getInputType() & InputType.TYPE_TEXT_FLAG_AUTO_CORRECT).isZero();
|
||||
assertThat(view.getInputType() & InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS).isZero();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAutoCapitalize() {
|
||||
ReactEditText view = mManager.createViewInstance(mThemedContext);
|
||||
|
||||
mManager.updateProperties(view, buildStyles());
|
||||
assertThat(view.getInputType() & InputType.TYPE_TEXT_FLAG_CAP_SENTENCES).isZero();
|
||||
assertThat(view.getInputType() & InputType.TYPE_TEXT_FLAG_CAP_WORDS).isZero();
|
||||
assertThat(view.getInputType() & InputType.TYPE_TEXT_FLAG_CAP_CHARACTERS).isZero();
|
||||
|
||||
mManager.updateProperties(
|
||||
view,
|
||||
buildStyles("autoCapitalize", InputType.TYPE_TEXT_FLAG_CAP_SENTENCES));
|
||||
assertThat(view.getInputType() & InputType.TYPE_TEXT_FLAG_CAP_SENTENCES).isNotZero();
|
||||
assertThat(view.getInputType() & InputType.TYPE_TEXT_FLAG_CAP_WORDS).isZero();
|
||||
assertThat(view.getInputType() & InputType.TYPE_TEXT_FLAG_CAP_CHARACTERS).isZero();
|
||||
|
||||
mManager.updateProperties(
|
||||
view,
|
||||
buildStyles("autoCapitalize", InputType.TYPE_TEXT_FLAG_CAP_WORDS));
|
||||
assertThat(view.getInputType() & InputType.TYPE_TEXT_FLAG_CAP_SENTENCES).isZero();
|
||||
assertThat(view.getInputType() & InputType.TYPE_TEXT_FLAG_CAP_WORDS).isNotZero();
|
||||
assertThat(view.getInputType() & InputType.TYPE_TEXT_FLAG_CAP_CHARACTERS).isZero();
|
||||
|
||||
mManager.updateProperties(
|
||||
view,
|
||||
buildStyles("autoCapitalize", InputType.TYPE_TEXT_FLAG_CAP_CHARACTERS));
|
||||
assertThat(view.getInputType() & InputType.TYPE_TEXT_FLAG_CAP_SENTENCES).isZero();
|
||||
assertThat(view.getInputType() & InputType.TYPE_TEXT_FLAG_CAP_WORDS).isZero();
|
||||
assertThat(view.getInputType() & InputType.TYPE_TEXT_FLAG_CAP_CHARACTERS).isNotZero();
|
||||
|
||||
mManager.updateProperties(
|
||||
view,
|
||||
buildStyles("autoCapitalize", InputType.TYPE_CLASS_TEXT));
|
||||
assertThat(view.getInputType() & InputType.TYPE_TEXT_FLAG_CAP_SENTENCES).isZero();
|
||||
assertThat(view.getInputType() & InputType.TYPE_TEXT_FLAG_CAP_WORDS).isZero();
|
||||
assertThat(view.getInputType() & InputType.TYPE_TEXT_FLAG_CAP_CHARACTERS).isZero();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPlaceholder() {
|
||||
ReactEditText view = mManager.createViewInstance(mThemedContext);
|
||||
mManager.updateProperties(view, buildStyles());
|
||||
assertThat(view.getHint()).isNull();
|
||||
|
||||
mManager.updateProperties(view, buildStyles("placeholder", "sometext"));
|
||||
assertThat(view.getHint()).isEqualTo("sometext");
|
||||
|
||||
mManager.updateProperties(view, buildStyles("placeholder", null));
|
||||
assertThat(view.getHint()).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEditable() {
|
||||
ReactEditText view = mManager.createViewInstance(mThemedContext);
|
||||
|
||||
mManager.updateProperties(view, buildStyles());
|
||||
assertThat(view.isEnabled()).isTrue();
|
||||
|
||||
mManager.updateProperties(view, buildStyles("editable", false));
|
||||
assertThat(view.isEnabled()).isFalse();
|
||||
|
||||
mManager.updateProperties(view, buildStyles("editable", null));
|
||||
assertThat(view.isEnabled()).isTrue();
|
||||
|
||||
mManager.updateProperties(view, buildStyles("editable", false));
|
||||
assertThat(view.isEnabled()).isFalse();
|
||||
|
||||
mManager.updateProperties(view, buildStyles("editable", true));
|
||||
assertThat(view.isEnabled()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPlaceholderTextColor() {
|
||||
ReactEditText view = mManager.createViewInstance(mThemedContext);
|
||||
|
||||
final ColorStateList defaultPlaceholderColorStateList =
|
||||
DefaultStyleValuesUtil.getDefaultTextColorHint(
|
||||
view.getContext());
|
||||
|
||||
ColorStateList colors = view.getHintTextColors();
|
||||
assertThat(colors).isEqualTo(defaultPlaceholderColorStateList);
|
||||
|
||||
mManager.updateProperties(view, buildStyles("placeholderTextColor", null));
|
||||
colors = view.getHintTextColors();
|
||||
assertThat(colors).isEqualTo(defaultPlaceholderColorStateList);
|
||||
|
||||
mManager.updateProperties(view, buildStyles("placeholderTextColor", Color.RED));
|
||||
colors = view.getHintTextColors();
|
||||
assertThat(colors.getDefaultColor()).isEqualTo(Color.RED);
|
||||
|
||||
mManager.updateProperties(view, buildStyles("placeholderTextColor", null));
|
||||
colors = view.getHintTextColors();
|
||||
assertThat(colors).isEqualTo(defaultPlaceholderColorStateList);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMultiline() {
|
||||
ReactEditText view = mManager.createViewInstance(mThemedContext);
|
||||
|
||||
mManager.updateProperties(view, buildStyles());
|
||||
assertThat(view.getInputType() & InputType.TYPE_TEXT_FLAG_MULTI_LINE).isZero();
|
||||
|
||||
mManager.updateProperties(view, buildStyles("multiline", false));
|
||||
assertThat(view.getInputType() & InputType.TYPE_TEXT_FLAG_MULTI_LINE).isZero();
|
||||
|
||||
mManager.updateProperties(view, buildStyles("multiline", true));
|
||||
assertThat(view.getInputType() & InputType.TYPE_TEXT_FLAG_MULTI_LINE).isNotZero();
|
||||
|
||||
mManager.updateProperties(view, buildStyles("multiline", null));
|
||||
assertThat(view.getInputType() & InputType.TYPE_TEXT_FLAG_MULTI_LINE).isZero();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNumLines() {
|
||||
ReactEditText view = mManager.createViewInstance(mThemedContext);
|
||||
|
||||
mManager.updateProperties(view, buildStyles());
|
||||
assertThat(view.getMinLines()).isEqualTo(1);
|
||||
|
||||
mManager.updateProperties(view, buildStyles("numberOfLines", 5));
|
||||
assertThat(view.getMinLines()).isEqualTo(5);
|
||||
|
||||
mManager.updateProperties(view, buildStyles("numberOfLines", 4));
|
||||
assertThat(view.getMinLines()).isEqualTo(4);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testKeyboardType() {
|
||||
ReactEditText view = mManager.createViewInstance(mThemedContext);
|
||||
|
||||
mManager.updateProperties(view, buildStyles());
|
||||
assertThat(view.getInputType() & InputType.TYPE_CLASS_NUMBER).isZero();
|
||||
|
||||
mManager.updateProperties(view, buildStyles("keyboardType", "text"));
|
||||
assertThat(view.getInputType() & InputType.TYPE_CLASS_NUMBER).isZero();
|
||||
|
||||
mManager.updateProperties(view, buildStyles("keyboardType", "numeric"));
|
||||
assertThat(view.getInputType() & InputType.TYPE_CLASS_NUMBER).isNotZero();
|
||||
|
||||
mManager.updateProperties(view, buildStyles("keyboardType", "email-address"));
|
||||
assertThat(view.getInputType() & InputType.TYPE_TEXT_VARIATION_EMAIL_ADDRESS).isNotZero();
|
||||
|
||||
mManager.updateProperties(view, buildStyles("keyboardType", null));
|
||||
assertThat(view.getInputType() & InputType.TYPE_CLASS_NUMBER).isZero();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPasswordInput() {
|
||||
ReactEditText view = mManager.createViewInstance(mThemedContext);
|
||||
|
||||
mManager.updateProperties(view, buildStyles());
|
||||
assertThat(view.getInputType() & InputType.TYPE_TEXT_VARIATION_PASSWORD).isZero();
|
||||
|
||||
mManager.updateProperties(view, buildStyles("password", false));
|
||||
assertThat(view.getInputType() & InputType.TYPE_TEXT_VARIATION_PASSWORD).isZero();
|
||||
|
||||
mManager.updateProperties(view, buildStyles("password", true));
|
||||
assertThat(view.getInputType() & InputType.TYPE_TEXT_VARIATION_PASSWORD).isNotZero();
|
||||
|
||||
mManager.updateProperties(view, buildStyles("password", null));
|
||||
assertThat(view.getInputType() & InputType.TYPE_TEXT_VARIATION_PASSWORD).isZero();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIncrementalInputTypeUpdates() {
|
||||
ReactEditText view = mManager.createViewInstance(mThemedContext);
|
||||
|
||||
mManager.updateProperties(view, buildStyles());
|
||||
assertThat(view.getInputType() & InputType.TYPE_CLASS_NUMBER).isZero();
|
||||
assertThat(view.getInputType() & InputType.TYPE_TEXT_FLAG_MULTI_LINE).isZero();
|
||||
assertThat(view.getInputType() & InputType.TYPE_TEXT_FLAG_AUTO_CORRECT).isZero();
|
||||
assertThat(view.getInputType() & InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS).isZero();
|
||||
|
||||
mManager.updateProperties(view, buildStyles("multiline", true));
|
||||
assertThat(view.getInputType() & InputType.TYPE_CLASS_NUMBER).isZero();
|
||||
assertThat(view.getInputType() & InputType.TYPE_TEXT_FLAG_MULTI_LINE).isNotZero();
|
||||
assertThat(view.getInputType() & InputType.TYPE_TEXT_FLAG_AUTO_CORRECT).isZero();
|
||||
assertThat(view.getInputType() & InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS).isZero();
|
||||
|
||||
mManager.updateProperties(view, buildStyles("autoCorrect", false));
|
||||
assertThat(view.getInputType() & InputType.TYPE_CLASS_NUMBER).isZero();
|
||||
assertThat(view.getInputType() & InputType.TYPE_TEXT_FLAG_MULTI_LINE).isNotZero();
|
||||
assertThat(view.getInputType() & InputType.TYPE_TEXT_FLAG_AUTO_CORRECT).isZero();
|
||||
assertThat(view.getInputType() & InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS).isNotZero();
|
||||
|
||||
mManager.updateProperties(view, buildStyles("keyboardType", "NUMERIC"));
|
||||
assertThat(view.getInputType() & InputType.TYPE_CLASS_NUMBER).isNotZero();
|
||||
assertThat(view.getInputType() & InputType.TYPE_TEXT_FLAG_MULTI_LINE).isNotZero();
|
||||
assertThat(view.getInputType() & InputType.TYPE_TEXT_FLAG_AUTO_CORRECT).isZero();
|
||||
assertThat(view.getInputType() & InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS).isNotZero();
|
||||
|
||||
mManager.updateProperties(view, buildStyles("multiline", null));
|
||||
assertThat(view.getInputType() & InputType.TYPE_CLASS_NUMBER).isNotZero();
|
||||
assertThat(view.getInputType() & InputType.TYPE_TEXT_FLAG_MULTI_LINE).isZero();
|
||||
assertThat(view.getInputType() & InputType.TYPE_TEXT_FLAG_AUTO_CORRECT).isZero();
|
||||
assertThat(view.getInputType() & InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS).isNotZero();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTextAlign() {
|
||||
ReactEditText view = mManager.createViewInstance(mThemedContext);
|
||||
int gravity = view.getGravity();
|
||||
assertThat(view.getGravity() & Gravity.BOTTOM).isNotEqualTo(Gravity.BOTTOM);
|
||||
|
||||
mManager.updateProperties(view, buildStyles("textAlignVertical", "bottom"));
|
||||
assertThat(view.getGravity() & Gravity.BOTTOM).isEqualTo(Gravity.BOTTOM);
|
||||
|
||||
mManager.updateProperties(
|
||||
view,
|
||||
buildStyles("textAlign", "right", "textAlignVertical", "top"));
|
||||
assertThat(view.getGravity() & Gravity.BOTTOM).isNotEqualTo(Gravity.BOTTOM);
|
||||
assertThat(view.getGravity() & (Gravity.RIGHT | Gravity.TOP))
|
||||
.isEqualTo(Gravity.RIGHT | Gravity.TOP);
|
||||
|
||||
mManager.updateProperties(
|
||||
view,
|
||||
buildStyles("textAlignVertical", null));
|
||||
assertThat(view.getGravity() & Gravity.RIGHT).isEqualTo(Gravity.RIGHT);
|
||||
assertThat(view.getGravity() & Gravity.TOP).isNotEqualTo(Gravity.TOP);
|
||||
|
||||
mManager.updateProperties(view, buildStyles("textAlign", null));
|
||||
assertThat(view.getGravity()).isEqualTo(gravity);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,191 @@
|
|||
/**
|
||||
* 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.views.textinput;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import android.view.Choreographer;
|
||||
import android.widget.EditText;
|
||||
|
||||
import com.facebook.react.ReactRootView;
|
||||
import com.facebook.react.bridge.Arguments;
|
||||
import com.facebook.react.bridge.ReactTestHelper;
|
||||
import com.facebook.react.bridge.ReactApplicationContext;
|
||||
import com.facebook.react.bridge.SimpleArray;
|
||||
import com.facebook.react.bridge.SimpleMap;
|
||||
import com.facebook.react.uimanager.ReactChoreographer;
|
||||
import com.facebook.react.uimanager.UIImplementation;
|
||||
import com.facebook.react.uimanager.UIManagerModule;
|
||||
import com.facebook.react.uimanager.ViewManager;
|
||||
import com.facebook.react.uimanager.ViewProps;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.Rule;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.invocation.InvocationOnMock;
|
||||
import org.mockito.stubbing.Answer;
|
||||
import org.powermock.api.mockito.PowerMockito;
|
||||
import org.powermock.core.classloader.annotations.PowerMockIgnore;
|
||||
import org.powermock.core.classloader.annotations.PrepareForTest;
|
||||
import org.powermock.modules.junit4.rule.PowerMockRule;
|
||||
import org.robolectric.Robolectric;
|
||||
import org.robolectric.RobolectricTestRunner;
|
||||
import org.robolectric.RuntimeEnvironment;
|
||||
|
||||
import static org.fest.assertions.api.Assertions.assertThat;
|
||||
import static org.mockito.Matchers.any;
|
||||
import static org.mockito.Mockito.doAnswer;
|
||||
import static org.mockito.Mockito.mock;
|
||||
|
||||
/**
|
||||
* Tests for TextInput.
|
||||
*/
|
||||
@PrepareForTest({Arguments.class, ReactChoreographer.class})
|
||||
@RunWith(RobolectricTestRunner.class)
|
||||
@PowerMockIgnore({"org.mockito.*", "org.robolectric.*", "android.*"})
|
||||
public class TextInputTest {
|
||||
|
||||
@Rule
|
||||
public PowerMockRule rule = new PowerMockRule();
|
||||
|
||||
private ArrayList<Choreographer.FrameCallback> mPendingChoreographerCallbacks;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
PowerMockito.mockStatic(Arguments.class, ReactChoreographer.class);
|
||||
|
||||
ReactChoreographer choreographerMock = mock(ReactChoreographer.class);
|
||||
PowerMockito.when(Arguments.createMap()).thenAnswer(new Answer<Object>() {
|
||||
@Override
|
||||
public Object answer(InvocationOnMock invocation) throws Throwable {
|
||||
return new SimpleMap();
|
||||
}
|
||||
});
|
||||
PowerMockito.when(ReactChoreographer.getInstance()).thenReturn(choreographerMock);
|
||||
|
||||
mPendingChoreographerCallbacks = new ArrayList<>();
|
||||
doAnswer(new Answer() {
|
||||
@Override
|
||||
public Object answer(InvocationOnMock invocation) throws Throwable {
|
||||
mPendingChoreographerCallbacks
|
||||
.add((Choreographer.FrameCallback) invocation.getArguments()[1]);
|
||||
return null;
|
||||
}
|
||||
}).when(choreographerMock).postFrameCallback(
|
||||
any(ReactChoreographer.CallbackType.class),
|
||||
any(Choreographer.FrameCallback.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPropsApplied() {
|
||||
UIManagerModule uiManager = getUIManagerModule();
|
||||
|
||||
ReactRootView rootView = new ReactRootView(RuntimeEnvironment.application);
|
||||
int rootTag = uiManager.addMeasuredRootView(rootView);
|
||||
int textInputTag = rootTag + 1;
|
||||
final String hintStr = "placeholder text";
|
||||
|
||||
uiManager.createView(
|
||||
textInputTag,
|
||||
ReactTextInputManager.REACT_CLASS,
|
||||
rootTag,
|
||||
SimpleMap.of(
|
||||
ViewProps.FONT_SIZE, 13.37, ViewProps.HEIGHT, 20.0, "placeholder", hintStr));
|
||||
|
||||
uiManager.manageChildren(
|
||||
rootTag,
|
||||
null,
|
||||
null,
|
||||
SimpleArray.of(textInputTag),
|
||||
SimpleArray.of(0),
|
||||
null);
|
||||
|
||||
uiManager.onBatchComplete();
|
||||
executePendingChoreographerCallbacks();
|
||||
|
||||
EditText editText = (EditText) rootView.getChildAt(0);
|
||||
assertThat(editText.getHint()).isEqualTo(hintStr);
|
||||
assertThat(editText.getTextSize()).isEqualTo((float) Math.ceil(13.37));
|
||||
assertThat(editText.getHeight()).isEqualTo(20);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPropsUpdate() {
|
||||
UIManagerModule uiManager = getUIManagerModule();
|
||||
|
||||
ReactRootView rootView = new ReactRootView(RuntimeEnvironment.application);
|
||||
int rootTag = uiManager.addMeasuredRootView(rootView);
|
||||
int textInputTag = rootTag + 1;
|
||||
final String hintStr = "placeholder text";
|
||||
|
||||
uiManager.createView(
|
||||
textInputTag,
|
||||
ReactTextInputManager.REACT_CLASS,
|
||||
rootTag,
|
||||
SimpleMap.of(
|
||||
ViewProps.FONT_SIZE, 13.37, ViewProps.HEIGHT, 20.0, "placeholder", hintStr));
|
||||
|
||||
uiManager.manageChildren(
|
||||
rootTag,
|
||||
null,
|
||||
null,
|
||||
SimpleArray.of(textInputTag),
|
||||
SimpleArray.of(0),
|
||||
null);
|
||||
uiManager.onBatchComplete();
|
||||
executePendingChoreographerCallbacks();
|
||||
|
||||
EditText editText = (EditText) rootView.getChildAt(0);
|
||||
assertThat(editText.getHint()).isEqualTo(hintStr);
|
||||
assertThat(editText.getTextSize()).isEqualTo((float) Math.ceil(13.37));
|
||||
assertThat(editText.getHeight()).isEqualTo(20);
|
||||
|
||||
final String hintStr2 = "such hint";
|
||||
uiManager.updateView(
|
||||
textInputTag,
|
||||
ReactTextInputManager.REACT_CLASS,
|
||||
SimpleMap.of(
|
||||
ViewProps.FONT_SIZE, 26.74, ViewProps.HEIGHT, 40.0, "placeholder", hintStr2));
|
||||
|
||||
uiManager.onBatchComplete();
|
||||
executePendingChoreographerCallbacks();
|
||||
|
||||
EditText updatedEditText = (EditText) rootView.getChildAt(0);
|
||||
assertThat(updatedEditText.getHint()).isEqualTo(hintStr2);
|
||||
assertThat(updatedEditText.getTextSize()).isEqualTo((float) Math.ceil(26.74f));
|
||||
assertThat(updatedEditText.getHeight()).isEqualTo(40);
|
||||
}
|
||||
|
||||
private void executePendingChoreographerCallbacks() {
|
||||
ArrayList<Choreographer.FrameCallback> callbacks =
|
||||
new ArrayList<>(mPendingChoreographerCallbacks);
|
||||
mPendingChoreographerCallbacks.clear();
|
||||
for (Choreographer.FrameCallback frameCallback : callbacks) {
|
||||
frameCallback.doFrame(0);
|
||||
}
|
||||
}
|
||||
|
||||
public UIManagerModule getUIManagerModule() {
|
||||
ReactApplicationContext reactContext = ReactTestHelper.createCatalystContextForTest();
|
||||
List<ViewManager> viewManagers = Arrays.asList(
|
||||
new ViewManager[] {
|
||||
new ReactTextInputManager(),
|
||||
});
|
||||
UIManagerModule uiManagerModule = new UIManagerModule(
|
||||
reactContext,
|
||||
viewManagers,
|
||||
new UIImplementation(reactContext, viewManagers));
|
||||
uiManagerModule.onHostResume();
|
||||
return uiManagerModule;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,53 @@
|
|||
/**
|
||||
* 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.views.view;
|
||||
|
||||
import android.graphics.PixelFormat;
|
||||
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.powermock.core.classloader.annotations.PowerMockIgnore;
|
||||
import org.powermock.modules.junit4.rule.PowerMockRule;
|
||||
import org.robolectric.RobolectricTestRunner;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
* Based on Fresco's DrawableUtilsTest (https://github.com/facebook/fresco).
|
||||
*/
|
||||
@RunWith(RobolectricTestRunner.class)
|
||||
@PowerMockIgnore({"org.mockito.*", "org.robolectric.*", "android.*"})
|
||||
public class ColorUtilTest {
|
||||
|
||||
@Rule
|
||||
public PowerMockRule rule = new PowerMockRule();
|
||||
|
||||
@Test
|
||||
public void testMultiplyColorAlpha() {
|
||||
assertEquals(0x00123456, ColorUtil.multiplyColorAlpha(0xC0123456, 0));
|
||||
assertEquals(0x07123456, ColorUtil.multiplyColorAlpha(0xC0123456, 10));
|
||||
assertEquals(0x96123456, ColorUtil.multiplyColorAlpha(0xC0123456, 200));
|
||||
assertEquals(0xC0123456, ColorUtil.multiplyColorAlpha(0xC0123456, 255));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetOpacityFromColor() {
|
||||
assertEquals(PixelFormat.TRANSPARENT, ColorUtil.getOpacityFromColor(0x00000000));
|
||||
assertEquals(PixelFormat.TRANSPARENT, ColorUtil.getOpacityFromColor(0x00123456));
|
||||
assertEquals(PixelFormat.TRANSPARENT, ColorUtil.getOpacityFromColor(0x00FFFFFF));
|
||||
assertEquals(PixelFormat.TRANSLUCENT, ColorUtil.getOpacityFromColor(0xC0000000));
|
||||
assertEquals(PixelFormat.TRANSLUCENT, ColorUtil.getOpacityFromColor(0xC0123456));
|
||||
assertEquals(PixelFormat.TRANSLUCENT, ColorUtil.getOpacityFromColor(0xC0FFFFFF));
|
||||
assertEquals(PixelFormat.OPAQUE, ColorUtil.getOpacityFromColor(0xFF000000));
|
||||
assertEquals(PixelFormat.OPAQUE, ColorUtil.getOpacityFromColor(0xFF123456));
|
||||
assertEquals(PixelFormat.OPAQUE, ColorUtil.getOpacityFromColor(0xFFFFFFFF));
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue