Use real YogaNodes in FabricReconcilerTest

Reviewed By: mdvacca

Differential Revision: D7664493

fbshipit-source-id: 74b088a91ea4f691cc15b5ea15dd585fe46e2035
This commit is contained in:
Andrew Chen (Eng) 2018-04-18 14:55:52 -07:00 committed by Facebook Github Bot
parent 850fd86942
commit af20958425
1 changed files with 28 additions and 52 deletions

View File

@ -4,22 +4,21 @@ package com.facebook.react.fabric;
import static org.fest.assertions.api.Assertions.assertThat; import static org.fest.assertions.api.Assertions.assertThat;
import static org.mockito.Mockito.mock; import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when; import static org.mockito.Mockito.when;
import static org.powermock.api.mockito.PowerMockito.mockStatic;
import com.facebook.react.bridge.CatalystInstance;
import com.facebook.react.bridge.ReactApplicationContext; import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.common.ClearableSynchronizedPool; import com.facebook.react.bridge.ReactTestHelper;
import com.facebook.react.fabric.FabricReconciler; import com.facebook.react.fabric.FabricReconciler;
import com.facebook.react.modules.core.ReactChoreographer; import com.facebook.react.fabric.FabricUIManager;
import com.facebook.react.uimanager.NativeViewHierarchyManager; import com.facebook.react.uimanager.NativeViewHierarchyManager;
import com.facebook.react.uimanager.ReactShadowNode; import com.facebook.react.uimanager.ReactShadowNode;
import com.facebook.react.uimanager.ReactShadowNodeImpl; import com.facebook.react.uimanager.ReactShadowNodeImpl;
import com.facebook.react.uimanager.ReactYogaConfigProvider;
import com.facebook.react.uimanager.UIViewOperationQueue; import com.facebook.react.uimanager.UIViewOperationQueue;
import com.facebook.react.uimanager.ViewAtIndex; import com.facebook.react.uimanager.ViewAtIndex;
import com.facebook.react.uimanager.YogaNodePool; import com.facebook.react.uimanager.ThemedReactContext;
import com.facebook.react.uimanager.ViewManager;
import com.facebook.react.uimanager.ViewManagerRegistry;
import com.facebook.testing.robolectric.v3.WithTestDefaultsRunner; import com.facebook.testing.robolectric.v3.WithTestDefaultsRunner;
import com.facebook.yoga.YogaConfig;
import com.facebook.yoga.YogaNode;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collections; import java.util.Collections;
@ -27,34 +26,27 @@ import java.util.List;
import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith; 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.robolectric.RuntimeEnvironment; import org.robolectric.RuntimeEnvironment;
/** Tests {@link FabricReconciler} */ /** Tests {@link FabricReconciler} */
@PrepareForTest({
ReactChoreographer.class,
ReactYogaConfigProvider.class,
YogaNodePool.class,
})
@RunWith(WithTestDefaultsRunner.class) @RunWith(WithTestDefaultsRunner.class)
@PowerMockIgnore({"org.mockito.*", "org.robolectric.*", "android.*"})
public class FabricReconcilerTest { public class FabricReconcilerTest {
private FabricReconciler mFabricReconciler; private FabricReconciler mFabricReconciler;
private FabricUIManager mFabricUIManager;
private MockUIViewOperationQueue mMockUIViewOperationQueue; private MockUIViewOperationQueue mMockUIViewOperationQueue;
@Before @Before
public void setUp() { public void setUp() {
CatalystInstance catalystInstance = ReactTestHelper.createMockCatalystInstance();
ReactApplicationContext reactContext = ReactApplicationContext reactContext =
new ReactApplicationContext(RuntimeEnvironment.application); new ReactApplicationContext(RuntimeEnvironment.application);
reactContext.initializeWithInstance(catalystInstance);
List<ViewManager> viewManagers = new ArrayList<>();
ViewManagerRegistry viewManagerRegistry = new ViewManagerRegistry(viewManagers);
mFabricUIManager = new FabricUIManager(reactContext, viewManagerRegistry);
mMockUIViewOperationQueue = new MockUIViewOperationQueue(reactContext); mMockUIViewOperationQueue = new MockUIViewOperationQueue(reactContext);
mFabricReconciler = new FabricReconciler(mMockUIViewOperationQueue); mFabricReconciler = new FabricReconciler(mMockUIViewOperationQueue);
setupHacks();
} }
@Test @Test
@ -98,6 +90,12 @@ public class FabricReconcilerTest {
assertThat(mMockUIViewOperationQueue.getOperations()).isEqualTo(expectedOperations); assertThat(mMockUIViewOperationQueue.getOperations()).isEqualTo(expectedOperations);
} }
private void addChildren(ReactShadowNode parent, ReactShadowNode... children) {
for (ReactShadowNode child : children) {
mFabricUIManager.appendChild(parent, child);
}
}
private static ReactShadowNode createNode(int tag) { private static ReactShadowNode createNode(int tag) {
return createNode(tag, false); return createNode(tag, false);
} }
@ -114,20 +112,26 @@ public class FabricReconcilerTest {
node = new ReactShadowNodeImpl(); node = new ReactShadowNodeImpl();
} }
node.setReactTag(tag); node.setReactTag(tag);
node.setThemedContext(mock(ThemedReactContext.class));
return node; return node;
} }
private static class VirtualReactShadowNode extends ReactShadowNodeImpl { private static class VirtualReactShadowNode extends ReactShadowNodeImpl {
VirtualReactShadowNode() {}
VirtualReactShadowNode(VirtualReactShadowNode original) {
super(original);
}
@Override @Override
public boolean isVirtual() { public boolean isVirtual() {
return true; return true;
} }
}
private static void addChildren(ReactShadowNode parent, ReactShadowNode... children) { @Override
for (ReactShadowNode child : children) { public ReactShadowNodeImpl copy() {
parent.addChildAt(child, parent.getChildCount()); return new VirtualReactShadowNode(this);
} }
} }
@ -193,32 +197,4 @@ public class FabricReconcilerTest {
return Collections.unmodifiableList(mOperations); return Collections.unmodifiableList(mOperations);
} }
} }
/** Hacks to get tests to start working end to end */
private void setupHacks() {
// Hack around Yoga by mocking it out until the UnsatisfiedLinkErrors are fixed t14964130
mockStatic(YogaNodePool.class, ReactYogaConfigProvider.class);
PowerMockito.when(YogaNodePool.get())
.thenAnswer(
new Answer<Object>() {
@Override
public Object answer(InvocationOnMock invocation) throws Exception {
ClearableSynchronizedPool<YogaNode> yogaPool =
mock(ClearableSynchronizedPool.class);
YogaNode yogaNode = mock(YogaNode.class);
when(yogaNode.clone()).thenReturn(mock(YogaNode.class));
when(yogaNode.isMeasureDefined()).thenReturn(true);
when(yogaPool.acquire()).thenReturn(yogaNode);
return yogaPool;
}
});
PowerMockito.when(ReactYogaConfigProvider.get())
.thenAnswer(
new Answer<Object>() {
@Override
public Object answer(InvocationOnMock invocation) {
return mock(YogaConfig.class);
}
});
}
} }