/** * 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.tests; import java.util.Arrays; import java.util.List; import com.facebook.react.bridge.CatalystInstance; import com.facebook.react.bridge.JavaScriptModule; import com.facebook.react.bridge.ObjectAlreadyConsumedException; import com.facebook.react.bridge.UiThreadUtil; import com.facebook.react.bridge.WritableArray; import com.facebook.react.bridge.WritableMap; import com.facebook.react.bridge.WritableNativeArray; import com.facebook.react.bridge.WritableNativeMap; import com.facebook.react.testing.AssertModule; import com.facebook.react.testing.FakeWebSocketModule; import com.facebook.react.testing.ReactIntegrationTestCase; import com.facebook.react.testing.ReactTestHelper; import com.facebook.react.uimanager.UIImplementationProvider; import com.facebook.react.uimanager.UIManagerModule; import com.facebook.react.uimanager.ViewManager; import com.facebook.react.views.view.ReactViewManager; /** * Test marshalling arguments from Java to JS to appropriate native classes. */ public class CatalystNativeJavaToJSArgumentsTestCase extends ReactIntegrationTestCase { private interface TestJavaToJSArgumentsModule extends JavaScriptModule { void receiveBasicTypes(String s, double d, boolean b, String nullString); void receiveArrayWithBasicTypes(WritableArray array); void receiveNestedArray(WritableArray nestedArray); void receiveArrayWithMaps(WritableArray arrayWithMaps); void receiveMapWithBasicTypes(WritableMap map); void receiveNestedMap(WritableMap nestedMap); void receiveMapWithArrays(WritableMap mapWithArrays); void receiveMapAndArrayWithNullValues( WritableMap map, WritableArray array); void receiveMapWithMultibyteUTF8CharacterString(WritableMap map); void receiveArrayWithMultibyteUTF8CharacterString(WritableArray array); } private AssertModule mAssertModule; private CatalystInstance mInstance; @Override protected void setUp() throws Exception { super.setUp(); List<ViewManager> viewManagers = Arrays.<ViewManager>asList( new ReactViewManager()); final UIManagerModule mUIManager = new UIManagerModule( getContext(), viewManagers, new UIImplementationProvider()); UiThreadUtil.runOnUiThread( new Runnable() { @Override public void run() { mUIManager.onHostResume(); } }); waitForIdleSync(); mAssertModule = new AssertModule(); mInstance = ReactTestHelper.catalystInstanceBuilder(this) .addNativeModule(mAssertModule) .addNativeModule(new FakeWebSocketModule()) .addJSModule(TestJavaToJSArgumentsModule.class) .addNativeModule(mUIManager) .build(); } public void testBasicTypes() { mInstance.getJSModule(TestJavaToJSArgumentsModule.class) .receiveBasicTypes("foo", 3.14, true, null); waitForBridgeAndUIIdle(); mAssertModule.verifyAssertsAndReset(); } public void testArrayWithBasicTypes() { WritableNativeArray array = new WritableNativeArray(); array.pushString("red panda"); array.pushDouble(1.19); array.pushBoolean(true); array.pushNull(); mInstance.getJSModule(TestJavaToJSArgumentsModule.class).receiveArrayWithBasicTypes(array); waitForBridgeAndUIIdle(); mAssertModule.verifyAssertsAndReset(); } public void testNestedArray() { WritableNativeArray level1 = new WritableNativeArray(); WritableNativeArray level2 = new WritableNativeArray(); WritableNativeArray level3 = new WritableNativeArray(); level3.pushString("level3"); level2.pushString("level2"); level2.pushArray(level3); level1.pushString("level1"); level1.pushArray(level2); mInstance.getJSModule(TestJavaToJSArgumentsModule.class).receiveNestedArray(level1); waitForBridgeAndUIIdle(); mAssertModule.verifyAssertsAndReset(); } public void testArrayWithMaps() { WritableNativeMap m1 = new WritableNativeMap(); WritableNativeMap m2 = new WritableNativeMap(); m1.putString("m1k1", "m1v1"); m1.putString("m1k2", "m1v2"); m2.putString("m2k1", "m2v1"); WritableNativeArray array = new WritableNativeArray(); array.pushMap(m1); array.pushMap(m2); mInstance.getJSModule(TestJavaToJSArgumentsModule.class).receiveArrayWithMaps(array); waitForBridgeAndUIIdle(); mAssertModule.verifyAssertsAndReset(); } public void testMapWithBasicTypes() { WritableNativeMap map = new WritableNativeMap(); map.putString("stringKey", "stringValue"); map.putDouble("doubleKey", 3.14); map.putBoolean("booleanKey", true); map.putNull("nullKey"); mInstance.getJSModule(TestJavaToJSArgumentsModule.class).receiveMapWithBasicTypes(map); waitForBridgeAndUIIdle(); mAssertModule.verifyAssertsAndReset(); } public void testNestedMap() { WritableNativeMap map = new WritableNativeMap(); WritableNativeMap nestedMap = new WritableNativeMap(); nestedMap.putString("animals", "foxes"); map.putMap("nestedMap", nestedMap); mInstance.getJSModule(TestJavaToJSArgumentsModule.class).receiveNestedMap(map); waitForBridgeAndUIIdle(); mAssertModule.verifyAssertsAndReset(); } public void testMapWithArrays() { WritableNativeMap map = new WritableNativeMap(); WritableNativeArray a1 = new WritableNativeArray(); WritableNativeArray a2 = new WritableNativeArray(); a1.pushDouble(3); a1.pushDouble(1); a1.pushDouble(4); a2.pushDouble(1); a2.pushDouble(9); map.putArray("array1", a1); map.putArray("array2", a2); mInstance.getJSModule(TestJavaToJSArgumentsModule.class).receiveMapWithArrays(map); waitForBridgeAndUIIdle(); mAssertModule.verifyAssertsAndReset(); } public void testMapWithNullStringValue() { WritableNativeMap map = new WritableNativeMap(); map.putString("string", null); map.putArray("array", null); map.putMap("map", null); WritableNativeArray array = new WritableNativeArray(); array.pushString(null); array.pushArray(null); array.pushMap(null); mInstance.getJSModule(TestJavaToJSArgumentsModule.class) .receiveMapAndArrayWithNullValues(map, array); waitForBridgeAndUIIdle(); mAssertModule.verifyAssertsAndReset(); } public void testStringWithMultibyteUTF8Characters() { TestJavaToJSArgumentsModule jsModule = mInstance.getJSModule(TestJavaToJSArgumentsModule.class); WritableNativeMap map = new WritableNativeMap(); map.putString("two-bytes", "\u00A2"); map.putString("three-bytes", "\u20AC"); map.putString("four-bytes", "\uD83D\uDE1C"); map.putString( "mixed", "\u017C\u00F3\u0142\u0107 g\u0119\u015Bl\u0105 \u6211 \uD83D\uDE0E ja\u017A\u0107"); jsModule.receiveMapWithMultibyteUTF8CharacterString(map); waitForBridgeAndUIIdle(); mAssertModule.verifyAssertsAndReset(); WritableArray array = new WritableNativeArray(); array.pushString("\u00A2"); array.pushString("\u20AC"); array.pushString("\uD83D\uDE1C"); array.pushString( "\u017C\u00F3\u0142\u0107 g\u0119\u015Bl\u0105 \u6211 \uD83D\uDE0E ja\u017A\u0107"); jsModule.receiveArrayWithMultibyteUTF8CharacterString(array); waitForBridgeAndUIIdle(); mAssertModule.verifyAssertsAndReset(); } public void testThrowWhenArrayReusedInArray() { boolean gotException = false; try { WritableNativeArray array1 = new WritableNativeArray(); WritableNativeArray array2 = new WritableNativeArray(); WritableNativeArray child = new WritableNativeArray(); array1.pushArray(child); array2.pushArray(child); } catch (ObjectAlreadyConsumedException e) { gotException = true; } assertTrue(gotException); } public void testThrowWhenArrayReusedInMap() { boolean gotException = false; try { WritableNativeMap map1 = new WritableNativeMap(); WritableNativeMap map2 = new WritableNativeMap(); WritableNativeArray child = new WritableNativeArray(); map1.putArray("child", child); map2.putArray("child", child); } catch (ObjectAlreadyConsumedException e) { gotException = true; } assertTrue(gotException); } public void testThrowWhenMapReusedInArray() { boolean gotException = false; try { WritableNativeArray array1 = new WritableNativeArray(); WritableNativeArray array2 = new WritableNativeArray(); WritableNativeMap child = new WritableNativeMap(); array1.pushMap(child); array2.pushMap(child); } catch (ObjectAlreadyConsumedException e) { gotException = true; } assertTrue(gotException); } public void testThrowWhenMapReusedInMap() { boolean gotException = false; try { WritableNativeMap map1 = new WritableNativeMap(); WritableNativeMap map2 = new WritableNativeMap(); WritableNativeMap child = new WritableNativeMap(); map1.putMap("child", child); map2.putMap("child", child); } catch (ObjectAlreadyConsumedException e) { gotException = true; } assertTrue(gotException); } public void testThrowWhenAddToConsumedArray() { WritableNativeArray array = new WritableNativeArray(); WritableNativeArray parent = new WritableNativeArray(); parent.pushArray(array); boolean gotException = false; try { array.pushNull(); } catch (ObjectAlreadyConsumedException e) { gotException = true; } assertTrue(gotException); gotException = false; try { array.pushBoolean(true); } catch (ObjectAlreadyConsumedException e) { gotException = true; } assertTrue(gotException); gotException = false; try { array.pushDouble(1); } catch (ObjectAlreadyConsumedException e) { gotException = true; } assertTrue(gotException); gotException = false; try { array.pushString("foo"); } catch (ObjectAlreadyConsumedException e) { gotException = true; } assertTrue(gotException); gotException = false; try { array.pushArray(new WritableNativeArray()); } catch (ObjectAlreadyConsumedException e) { gotException = true; } assertTrue(gotException); gotException = false; try { array.pushMap(new WritableNativeMap()); } catch (ObjectAlreadyConsumedException e) { gotException = true; } assertTrue(gotException); } public void testThrowWhenAddToConsumedMap() { WritableNativeMap map = new WritableNativeMap(); WritableNativeArray parent = new WritableNativeArray(); parent.pushMap(map); boolean gotException = false; try { map.putNull("key"); } catch (ObjectAlreadyConsumedException e) { gotException = true; } assertTrue(gotException); gotException = false; try { map.putBoolean("key", true); } catch (ObjectAlreadyConsumedException e) { gotException = true; } assertTrue(gotException); gotException = false; try { map.putDouble("key", 1); } catch (ObjectAlreadyConsumedException e) { gotException = true; } assertTrue(gotException); gotException = false; try { map.putString("key", "foo"); } catch (ObjectAlreadyConsumedException e) { gotException = true; } assertTrue(gotException); gotException = false; try { map.putArray("key", new WritableNativeArray()); } catch (ObjectAlreadyConsumedException e) { gotException = true; } assertTrue(gotException); gotException = false; try { map.putMap("key", new WritableNativeMap()); } catch (ObjectAlreadyConsumedException e) { gotException = true; } assertTrue(gotException); } }