diff --git a/ReactAndroid/src/androidTest/buck-runner/BUCK b/ReactAndroid/src/androidTest/buck-runner/BUCK index b513e807e..35dd36862 100644 --- a/ReactAndroid/src/androidTest/buck-runner/BUCK +++ b/ReactAndroid/src/androidTest/buck-runner/BUCK @@ -3,7 +3,7 @@ include_defs('//ReactAndroid/DEFS') # We are running instrumentation tests in simple mode: app code and instrumentation are in the same APK # Currently you need to run these commands to execute tests: # -# node local-cli/cli.js bundle --platform android --dev true --entry-file ReactAndroid/src/androidTest/assets/TestBundle.js --bundle-output ReactAndroid/src/androidTest/assets/AndroidTestBundle.js +# node local-cli/cli.js bundle --platform android --dev true --entry-file ReactAndroid/src/androidTest/js/TestBundle.js --bundle-output ReactAndroid/src/androidTest/assets/AndroidTestBundle.js # gradle :ReactAndroid:packageReactNdkLibsForBuck # buck install ReactAndroid/src/androidTest/buck-runner:instrumentation-tests # ./scripts/run-android-instrumentation-tests.sh com.facebook.react.tests @@ -12,13 +12,12 @@ android_binary( manifest = 'AndroidManifest.xml', keystore = '//keystores:debug', deps = [ - react_native_integration_tests_target('java/com/facebook/react/tests:tests'), - react_native_integration_tests_target('assets:assets'), - react_native_dep('third-party/java/testing-support-lib:exposed-instrumentation-api'), - react_native_target('jni/prebuilt:reactnative-libs'), - react_native_target('jni/prebuilt:android-jsc'), react_native_dep('libraries/soloader/java/com/facebook/soloader:soloader'), + react_native_dep('third-party/java/testing-support-lib:exposed-instrumentation-api'), + react_native_integration_tests_target('assets:assets'), + react_native_integration_tests_target('java/com/facebook/react/tests:tests'), react_native_target('java/com/facebook/react/devsupport:devsupport'), + react_native_target('jni/prebuilt:android-jsc'), + react_native_target('jni/prebuilt:reactnative-libs'), ], ) - diff --git a/ReactAndroid/src/androidTest/java/com/facebook/react/tests/BUCK b/ReactAndroid/src/androidTest/java/com/facebook/react/tests/BUCK index 78d23f135..b82f0747f 100644 --- a/ReactAndroid/src/androidTest/java/com/facebook/react/tests/BUCK +++ b/ReactAndroid/src/androidTest/java/com/facebook/react/tests/BUCK @@ -7,6 +7,7 @@ android_library( react_native_integration_tests_target('java/com/facebook/react/testing:testing'), react_native_target('java/com/facebook/react/bridge:bridge'), react_native_target('java/com/facebook/react/uimanager:uimanager'), + react_native_target('java/com/facebook/react/views/picker:picker'), ], visibility = [ 'PUBLIC', diff --git a/ReactAndroid/src/androidTest/java/com/facebook/react/tests/ReactPickerTestCase.java b/ReactAndroid/src/androidTest/java/com/facebook/react/tests/ReactPickerTestCase.java new file mode 100644 index 000000000..fcba6412f --- /dev/null +++ b/ReactAndroid/src/androidTest/java/com/facebook/react/tests/ReactPickerTestCase.java @@ -0,0 +1,178 @@ +/** + * Copyright (c) 2014-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.ArrayList; +import java.util.List; + +import android.graphics.Color; +import android.widget.Spinner; +import android.widget.SpinnerAdapter; +import android.widget.TextView; + +import com.facebook.react.bridge.BaseJavaModule; +import com.facebook.react.testing.ReactInstanceSpecForTest; +import com.facebook.react.bridge.ReactMethod; +import com.facebook.react.bridge.JavaScriptModule; +import com.facebook.react.views.picker.ReactDialogPickerManager; +import com.facebook.react.views.picker.ReactDropdownPickerManager; +import com.facebook.react.views.picker.ReactPicker; +import com.facebook.react.views.picker.ReactPickerManager; +import com.facebook.react.testing.ReactAppInstrumentationTestCase; + +/** + * Integration test for {@link ReactDialogPickerManager} and {@link ReactDropdownPickerManager} + * (and, implicitly, {@link ReactPickerManager}). Tests basic properties, events and switching + * between spinner modes (which changes the used manager). + */ +public class ReactPickerTestCase extends ReactAppInstrumentationTestCase { + + private static interface PickerAndroidTestModule extends JavaScriptModule { + public void selectItem(int position); + public void setMode(String mode); + public void setPrimaryColor(String color); + } + + public static class PickerAndroidRecordingModule extends BaseJavaModule { + private final List mSelections = new ArrayList(); + + @Override + public String getName() { + return "PickerAndroidRecordingModule"; + } + + @ReactMethod + public void recordSelection(int position) { + mSelections.add(position); + } + + public List getSelections() { + return new ArrayList(mSelections); + } + } + + private PickerAndroidRecordingModule mRecordingModule; + + @Override + protected String getReactApplicationKeyUnderTest() { + return "PickerAndroidTestApp"; + } + + @Override + protected ReactInstanceSpecForTest createReactInstanceSpecForTest() { + mRecordingModule = new PickerAndroidRecordingModule(); + return super.createReactInstanceSpecForTest() + .addJSModule(PickerAndroidTestModule.class) + .addNativeModule(mRecordingModule); + } + + public void testBasicProperties() { + ReactPicker spinner = getViewAtPath(0, 0); + SpinnerAdapter adapter = spinner.getAdapter(); + + assertEquals(Spinner.MODE_DIALOG, spinner.getMode()); + assertEquals("prompt", spinner.getPrompt()); + assertNotNull(adapter); + assertEquals(3, adapter.getCount()); + assertEquals("item1", ((TextView) adapter.getView(0, null, null)).getText()); + assertEquals("item2", ((TextView) adapter.getView(1, null, null)).getText()); + assertEquals("item3", ((TextView) adapter.getView(2, null, null)).getText()); + assertEquals(1, spinner.getSelectedItemPosition()); + + // test colors + assertEquals(Color.RED, ((TextView) adapter.getView(0, null, null)).getCurrentTextColor()); + assertEquals(Color.GREEN, ((TextView) adapter.getView(1, null, null)).getCurrentTextColor()); + assertEquals(Color.BLUE, ((TextView) adapter.getView(2, null, null)).getCurrentTextColor()); + assertEquals( + Color.RED, + ((TextView) adapter.getDropDownView(0, null, null)).getCurrentTextColor()); + assertEquals( + Color.GREEN, + ((TextView) adapter.getDropDownView(1, null, null)).getCurrentTextColor()); + assertEquals( + Color.BLUE, + ((TextView) adapter.getDropDownView(2, null, null)).getCurrentTextColor()); + getTestModule().setPrimaryColor("black"); + waitForBridgeAndUIIdle(); + assertEquals(Color.BLACK, ((TextView) adapter.getView(0, null, null)).getCurrentTextColor()); + assertEquals(Color.BLACK, ((TextView) adapter.getView(1, null, null)).getCurrentTextColor()); + assertEquals(Color.BLACK, ((TextView) adapter.getView(2, null, null)).getCurrentTextColor()); + assertEquals( + Color.RED, + ((TextView) adapter.getDropDownView(0, null, null)).getCurrentTextColor()); + assertEquals( + Color.GREEN, + ((TextView) adapter.getDropDownView(1, null, null)).getCurrentTextColor()); + assertEquals( + Color.BLUE, + ((TextView) adapter.getDropDownView(2, null, null)).getCurrentTextColor()); + + } + + public void testDropdownPicker() { + ReactPicker spinner = getViewAtPath(0, 1); + + assertEquals(Spinner.MODE_DROPDOWN, spinner.getMode()); + } + + public void testDisabledPicker() { + ReactPicker spinner = getViewAtPath(0, 2); + + assertFalse(spinner.isEnabled()); + } + + public void testUpdateSelectedItem() { + ReactPicker spinner = getViewAtPath(0, 0); + assertEquals(1, spinner.getSelectedItemPosition()); + + getTestModule().selectItem(2); + waitForBridgeAndUIIdle(); + getInstrumentation().waitForIdleSync(); + + assertEquals(2, spinner.getSelectedItemPosition()); + } + + public void testUpdateMode() { + ReactPicker spinner = getViewAtPath(0, 1); + assertEquals(Spinner.MODE_DROPDOWN, spinner.getMode()); + + getTestModule().setMode("dialog"); + waitForBridgeAndUIIdle(); + getInstrumentation().waitForIdleSync(); + + // changing the spinner mode in JS actually creates a new component on the native side, as + // there's no way to change the mode once you have constructed a Spinner. + ReactPicker newPicker = getViewAtPath(0, 1); + assertTrue(spinner != newPicker); + assertEquals(Spinner.MODE_DIALOG, newPicker.getMode()); + } + + public void testOnSelect() throws Throwable { + runTestOnUiThread( + new Runnable() { + @Override + public void run() { + ReactPicker spinner = getViewAtPath(0, 0); + spinner.setSelection(2); + } + }); + + getInstrumentation().waitForIdleSync(); + waitForBridgeAndUIIdle(); + + List selections = mRecordingModule.getSelections(); + assertEquals(1, selections.size()); + assertEquals(2, (int) selections.get(0)); + } + + private PickerAndroidTestModule getTestModule() { + return getReactContext().getCatalystInstance().getJSModule(PickerAndroidTestModule.class); + } + +} diff --git a/ReactAndroid/src/androidTest/js/PickerAndroidTestModule.js b/ReactAndroid/src/androidTest/js/PickerAndroidTestModule.js new file mode 100644 index 000000000..95e31937d --- /dev/null +++ b/ReactAndroid/src/androidTest/js/PickerAndroidTestModule.js @@ -0,0 +1,82 @@ +/** + * Copyright (c) 2013-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. + * + * @providesModule PickerAndroidTestModule + */ + +'use strict'; + +var BatchedBridge = require('BatchedBridge'); +var React = require('React'); +var RecordingModule = require('NativeModules').PickerAndroidRecordingModule; +var Picker = require('Picker'); +var View = require('View'); + +var Item = Picker.Item; + +var appInstance; +var PickerAndroidTestApp = React.createClass({ + componentWillMount: function() { + appInstance = this; + }, + getInitialState: function() { + return { + selected: 1, + mode: 'dropdown', + style: {}, + }; + }, + render: function() { + return ( + + + + + + + + + + + + + + + + ); + }, + onValueChange: function(value) { + this.setState({selected: value}); + RecordingModule.recordSelection(value); + }, +}); + +var PickerAndroidTestModule = { + PickerAndroidTestApp: PickerAndroidTestApp, + selectItem: function(value) { + appInstance.setState({selected: value}); + }, + setMode: function(mode) { + appInstance.setState({mode: mode}); + }, + setPrimaryColor: function(color) { + appInstance.setState({style: {color}}); + }, +}; + +BatchedBridge.registerCallableModule( + 'PickerAndroidTestModule', + PickerAndroidTestModule +); + +module.exports = PickerAndroidTestModule; diff --git a/ReactAndroid/src/androidTest/assets/ScrollViewTestModule.js b/ReactAndroid/src/androidTest/js/ScrollViewTestModule.js similarity index 91% rename from ReactAndroid/src/androidTest/assets/ScrollViewTestModule.js rename to ReactAndroid/src/androidTest/js/ScrollViewTestModule.js index e7dac8c7e..ac4f5f1a5 100644 --- a/ReactAndroid/src/androidTest/assets/ScrollViewTestModule.js +++ b/ReactAndroid/src/androidTest/js/ScrollViewTestModule.js @@ -1,4 +1,11 @@ /** + * Copyright (c) 2013-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. + * * @providesModule ScrollViewTestModule */ diff --git a/ReactAndroid/src/androidTest/assets/TestBundle.js b/ReactAndroid/src/androidTest/js/TestBundle.js similarity index 67% rename from ReactAndroid/src/androidTest/assets/TestBundle.js rename to ReactAndroid/src/androidTest/js/TestBundle.js index 1bbdad734..05c71eb9f 100644 --- a/ReactAndroid/src/androidTest/assets/TestBundle.js +++ b/ReactAndroid/src/androidTest/js/TestBundle.js @@ -1,9 +1,11 @@ /** - * Copyright (c) 2014-present, Facebook, Inc. + * Copyright (c) 2013-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. + * */ 'use strict'; @@ -12,19 +14,25 @@ console.disableYellowBox = true; // Include modules used by integration tests require('ScrollViewTestModule'); +require('PickerAndroidTestModule'); // Define catalyst test apps used in integration tests var AppRegistry = require('AppRegistry'); var apps = [ { - appKey: 'ScrollViewTestApp', - component: () => require('ScrollViewTestModule').ScrollViewTestApp + appKey: 'ScrollViewTestApp', + component: () => require('ScrollViewTestModule').ScrollViewTestApp, }, { appKey: 'HorizontalScrollViewTestApp', - component: () => require('ScrollViewTestModule').HorizontalScrollViewTestApp + component: () => require('ScrollViewTestModule').HorizontalScrollViewTestApp, +}, +{ + appKey: 'PickerAndroidTestApp', + component: () => require('PickerAndroidTestModule').PickerAndroidTestApp, }, ]; +module.exports = apps; AppRegistry.registerConfig(apps); diff --git a/circle.yml b/circle.yml index b6d43b6b6..569cf98b5 100644 --- a/circle.yml +++ b/circle.yml @@ -65,7 +65,7 @@ test: - ./gradlew :ReactAndroid:packageReactNdkLibsForBuck -Pjobs=1: timeout: 360 # build JS bundle for instrumentation tests - - node local-cli/cli.js bundle --platform android --dev true --entry-file ReactAndroid/src/androidTest/assets/TestBundle.js --bundle-output ReactAndroid/src/androidTest/assets/AndroidTestBundle.js + - node local-cli/cli.js bundle --platform android --dev true --entry-file ReactAndroid/src/androidTest/js/TestBundle.js --bundle-output ReactAndroid/src/androidTest/assets/AndroidTestBundle.js # build test APK - buck install ReactAndroid/src/androidTest/buck-runner:instrumentation-tests --config build.threads=1 # run installed apk with tests