diff --git a/ReactAndroid/src/androidTest/java/com/facebook/react/tests/CatalystMeasureLayoutTest.java b/ReactAndroid/src/androidTest/java/com/facebook/react/tests/CatalystMeasureLayoutTest.java new file mode 100644 index 000000000..ba34dda08 --- /dev/null +++ b/ReactAndroid/src/androidTest/java/com/facebook/react/tests/CatalystMeasureLayoutTest.java @@ -0,0 +1,131 @@ +/** + * 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 com.facebook.react.testing.ReactInstanceSpecForTest; +import com.facebook.react.bridge.JavaScriptModule; +import com.facebook.react.uimanager.UIManagerModule; +import com.facebook.react.testing.AssertModule; +import com.facebook.react.testing.ReactAppInstrumentationTestCase; + +/** + * Tests for {@link UIManagerModule#measure}, {@link UIManagerModule#measureLayout}, and + * {@link UIManagerModule#measureLayoutRelativeToParent}. Tests measurement for views in the + * following hierarchy: + * + * +---------------------------------------------+ + * | A | + * | | + * | +-----------+ +---------+ | + * | | B | | D | | + * | | +---+ | | | | + * | | | C | | | | | + * | | | | | +---------+ | + * | | +---+ | | + * | +-----------+ | + * | | + * | | + * | | + * +---------------------------------------------+ + * + * View locations and dimensions: + * A - (0,0) to (500, 500) (500x500) + * B - (50,80) to (250, 380) (200x300) + * C - (150,150) to (200, 300) (50x150) + * D - (400,100) to (450, 300) (50x200) + */ +public class CatalystMeasureLayoutTest extends ReactAppInstrumentationTestCase { + + private static interface MeasureLayoutTestModule extends JavaScriptModule { + public void verifyMeasureOnViewA(); + public void verifyMeasureOnViewC(); + public void verifyMeasureLayoutCRelativeToA(); + public void verifyMeasureLayoutCRelativeToB(); + public void verifyMeasureLayoutCRelativeToSelf(); + public void verifyMeasureLayoutRelativeToParentOnViewA(); + public void verifyMeasureLayoutRelativeToParentOnViewB(); + public void verifyMeasureLayoutRelativeToParentOnViewC(); + public void verifyMeasureLayoutDRelativeToB(); + public void verifyMeasureLayoutNonExistentTag(); + public void verifyMeasureLayoutNonExistentAncestor(); + public void verifyMeasureLayoutRelativeToParentNonExistentTag(); + } + + private MeasureLayoutTestModule mTestJSModule; + private AssertModule mAssertModule; + + @Override + protected void setUp() throws Exception { + super.setUp(); + mTestJSModule = getReactContext().getJSModule(MeasureLayoutTestModule.class); + } + + @Override + protected String getReactApplicationKeyUnderTest() { + return "MeasureLayoutTestApp"; + } + + @Override + protected ReactInstanceSpecForTest createReactInstanceSpecForTest() { + mAssertModule = new AssertModule(); + return new ReactInstanceSpecForTest() + .addNativeModule(mAssertModule) + .addJSModule(MeasureLayoutTestModule.class); + } + + private void waitForBridgeIdleAndVerifyAsserts() { + waitForBridgeAndUIIdle(); + mAssertModule.verifyAssertsAndReset(); + } + + public void testMeasure() { + mTestJSModule.verifyMeasureOnViewA(); + waitForBridgeIdleAndVerifyAsserts(); + mTestJSModule.verifyMeasureOnViewC(); + waitForBridgeIdleAndVerifyAsserts(); + } + + public void testMeasureLayout() { + mTestJSModule.verifyMeasureLayoutCRelativeToA(); + waitForBridgeIdleAndVerifyAsserts(); + mTestJSModule.verifyMeasureLayoutCRelativeToB(); + waitForBridgeIdleAndVerifyAsserts(); + mTestJSModule.verifyMeasureLayoutCRelativeToSelf(); + waitForBridgeIdleAndVerifyAsserts(); + } + + public void testMeasureLayoutRelativeToParent() { + mTestJSModule.verifyMeasureLayoutRelativeToParentOnViewA(); + waitForBridgeIdleAndVerifyAsserts(); + mTestJSModule.verifyMeasureLayoutRelativeToParentOnViewB(); + waitForBridgeIdleAndVerifyAsserts(); + mTestJSModule.verifyMeasureLayoutRelativeToParentOnViewC(); + waitForBridgeIdleAndVerifyAsserts(); + } + + public void testMeasureLayoutCallsErrorCallbackWhenViewIsNotChildOfAncestor() { + mTestJSModule.verifyMeasureLayoutDRelativeToB(); + waitForBridgeIdleAndVerifyAsserts(); + } + + public void testMeasureLayoutCallsErrorCallbackWhenViewDoesNotExist() { + mTestJSModule.verifyMeasureLayoutNonExistentTag(); + waitForBridgeIdleAndVerifyAsserts(); + } + + public void testMeasureLayoutCallsErrorCallbackWhenAncestorDoesNotExist() { + mTestJSModule.verifyMeasureLayoutNonExistentAncestor(); + waitForBridgeIdleAndVerifyAsserts(); + } + + public void testMeasureLayoutRelativeToParentCallsErrorCallbackWhenViewDoesNotExist() { + mTestJSModule.verifyMeasureLayoutRelativeToParentNonExistentTag(); + waitForBridgeIdleAndVerifyAsserts(); + } +} diff --git a/ReactAndroid/src/androidTest/js/MeasureLayoutTestModule.js b/ReactAndroid/src/androidTest/js/MeasureLayoutTestModule.js new file mode 100644 index 000000000..2bec77352 --- /dev/null +++ b/ReactAndroid/src/androidTest/js/MeasureLayoutTestModule.js @@ -0,0 +1,205 @@ +/** + * 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 MeasureLayoutTestModule + */ + +'use strict'; + +var BatchedBridge = require('BatchedBridge'); +var React = require('React'); +var ReactNative = require('ReactNative'); +var View = require('View'); +var StyleSheet = require('StyleSheet'); +var UIManager = require('UIManager'); + +var assertEquals = require('Asserts').assertEquals; + +var styles = StyleSheet.create({ + A: { + "width": 500, + "height": 500, + }, + B: { + backgroundColor: "rgb(255, 0, 0)", + "left": 50, + "top": 80, + "width": 200, + "height": 300, + }, + C: { + backgroundColor: "rgb(0, 255, 0)", + "left": 100, + "top": 70, + "width": 50, + "height": 150, + }, + D: { + backgroundColor: "rgb(0, 0, 255)", + "left": 400, + "top": 100, + "width": 50, + "height": 200, + }, +}); + +var A, B, C, D; + +var MeasureLayoutTestApp = React.createClass({ + componentDidMount: function() { + A = ReactNative.findNodeHandle(this.refs.A); + B = ReactNative.findNodeHandle(this.refs.B); + C = ReactNative.findNodeHandle(this.refs.C); + D = ReactNative.findNodeHandle(this.refs.D); + }, + render: function() { + return ( + + + + + + + ); + }, +}); + +function shouldNotCallThisCallback() { + assertEquals(false, true); +} + +var MeasureLayoutTestModule = { + MeasureLayoutTestApp: MeasureLayoutTestApp, + verifyMeasureOnViewA: function() { + UIManager.measure(A, function(a, b, width, height, x, y) { + assertEquals(500, width); + assertEquals(500, height); + assertEquals(0, x); + assertEquals(0, y); + }); + }, + verifyMeasureOnViewC: function() { + UIManager.measure(C, function(a, b, width, height, x, y) { + assertEquals(50, width); + assertEquals(150, height); + assertEquals(150, x); + assertEquals(150, y); + }); + }, + verifyMeasureLayoutCRelativeToA: function() { + UIManager.measureLayout( + C, + A, + shouldNotCallThisCallback, + function (x, y, width, height) { + assertEquals(50, width); + assertEquals(150, height); + assertEquals(150, x); + assertEquals(150, y); + }); + }, + verifyMeasureLayoutCRelativeToB: function() { + UIManager.measureLayout( + C, + B, + shouldNotCallThisCallback, + function (x, y, width, height) { + assertEquals(50, width); + assertEquals(150, height); + assertEquals(100, x); + assertEquals(70, y); + }); + }, + verifyMeasureLayoutCRelativeToSelf: function() { + UIManager.measureLayout( + C, + C, + shouldNotCallThisCallback, + function (x, y, width, height) { + assertEquals(50, width); + assertEquals(150, height); + assertEquals(0, x); + assertEquals(0, y); + }); + }, + verifyMeasureLayoutRelativeToParentOnViewA: function() { + UIManager.measureLayoutRelativeToParent( + A, + shouldNotCallThisCallback, + function (x, y, width, height) { + assertEquals(500, width); + assertEquals(500, height); + assertEquals(0, x); + assertEquals(0, y); + }); + }, + verifyMeasureLayoutRelativeToParentOnViewB: function() { + UIManager.measureLayoutRelativeToParent( + B, + shouldNotCallThisCallback, + function (x, y, width, height) { + assertEquals(200, width); + assertEquals(300, height); + assertEquals(50, x); + assertEquals(80, y); + }); + }, + verifyMeasureLayoutRelativeToParentOnViewC: function() { + UIManager.measureLayoutRelativeToParent( + C, + shouldNotCallThisCallback, + function (x, y, width, height) { + assertEquals(50, width); + assertEquals(150, height); + assertEquals(100, x); + assertEquals(70, y); + }); + }, + verifyMeasureLayoutDRelativeToB: function() { + UIManager.measureLayout( + D, + B, + function () { + assertEquals(true, true); + }, + shouldNotCallThisCallback); + }, + verifyMeasureLayoutNonExistentTag: function() { + UIManager.measureLayout( + 192, + A, + function () { + assertEquals(true, true); + }, + shouldNotCallThisCallback); + }, + verifyMeasureLayoutNonExistentAncestor: function() { + UIManager.measureLayout( + B, + 192, + function () { + assertEquals(true, true); + }, + shouldNotCallThisCallback); + }, + verifyMeasureLayoutRelativeToParentNonExistentTag: function() { + UIManager.measureLayoutRelativeToParent( + 192, + function () { + assertEquals(true, true); + }, + shouldNotCallThisCallback); + }, +}; + +BatchedBridge.registerCallableModule( + 'MeasureLayoutTestModule', + MeasureLayoutTestModule +); + +module.exports = MeasureLayoutTestModule; diff --git a/ReactAndroid/src/androidTest/js/TestBundle.js b/ReactAndroid/src/androidTest/js/TestBundle.js index 39eb37c7b..8dcae7d0b 100644 --- a/ReactAndroid/src/androidTest/js/TestBundle.js +++ b/ReactAndroid/src/androidTest/js/TestBundle.js @@ -18,14 +18,16 @@ require('ViewRenderingTestModule'); require('TestJavaToJSArgumentsModule'); require('TestJSToJavaParametersModule'); -require('PickerAndroidTestModule'); require('CatalystRootViewTestModule'); require('DatePickerDialogTestModule'); +require('MeasureLayoutTestModule'); +require('PickerAndroidTestModule'); require('ScrollViewTestModule'); require('SwipeRefreshLayoutTestModule'); require('TextInputTestModule'); require('TimePickerDialogTestModule'); + // Define catalyst test apps used in integration tests var AppRegistry = require('AppRegistry'); @@ -42,6 +44,10 @@ var apps = [ appKey: 'HorizontalScrollViewTestApp', component: () => require('ScrollViewTestModule').HorizontalScrollViewTestApp, }, +{ + appKey: 'MeasureLayoutTestApp', + component: () => require('MeasureLayoutTestModule').MeasureLayoutTestApp +}, { appKey: 'MultitouchHandlingTestAppModule', component: () => require('MultitouchHandlingTestAppModule')