/** * Update the width/height spec. This is useful if you are currently detached and are responding * to a configuration change. If you are currently attached then the HostView is the source of * truth for width/height, so this call will be ignored. */ public void setSizeSpec(int widthSpec, int heightSpec) { setSizeSpec(widthSpec, heightSpec, null); }
@Test public void testSetSizeSpecAsyncThenSyncAfterRunningTask() { ComponentTree componentTree = ComponentTree.create(mContext, mComponent) .build(); componentTree.setSizeSpecAsync(mWidthSpec, mHeightSpec); mLayoutThreadShadowLooper.runToEndOfTasks(); componentTree.setSizeSpec(mWidthSpec2, mHeightSpec2); // Since this happens post creation, it's not in general safe to update the main thread layout // state synchronously, so the result should be in the background layout state postSizeSpecChecks( componentTree, "mBackgroundLayoutState", mWidthSpec2, mHeightSpec2); }
@Test public void testListenerNotInvokedWhenNewMeasureSpecsAreCompatible() { mComponentTree.setLithoView(new LithoView(mContext)); mComponentTree.attach(); mComponentTree.setSizeSpec(mWidthSpec, mHeightSpec); mComponentTree.setNewLayoutStateReadyListener(mListener); mComponentTree.setSizeSpec(mWidthSpec, mHeightSpec); verify(mListener, never()).onNewLayoutStateReady(mComponentTree); } }
@Test public void testSetSizeSpecAsyncThenSyncBeforeRunningTask() { ComponentTree componentTree = ComponentTree.create(mContext, mComponent) .build(); componentTree.setSizeSpecAsync(mWidthSpec, mHeightSpec); componentTree.setSizeSpec(mWidthSpec2, mHeightSpec2); mLayoutThreadShadowLooper.runToEndOfTasks(); // Since this happens post creation, it's not in general safe to update the main thread layout // state synchronously, so the result should be in the background layout state postSizeSpecChecks( componentTree, "mBackgroundLayoutState", mWidthSpec2, mHeightSpec2); }
@Test public void testListenerNotInvokedWhenMeasureDoesntComputeALayout() { mComponentTree.setNewLayoutStateReadyListener(mListener); mComponentTree.setLithoView(new LithoView(mContext)); mComponentTree.attach(); mComponentTree.setSizeSpec(mWidthSpec, mHeightSpec); verify(mListener).onNewLayoutStateReady(mComponentTree); reset(mListener); mComponentTree.measure(mWidthSpec, mHeightSpec, new int[] {0, 0}, false); verify(mListener, never()).onNewLayoutStateReady(mComponentTree); }
@Test public void testListenerInvokedForMeasure() { mComponentTree.setNewLayoutStateReadyListener(mListener); mComponentTree.setLithoView(new LithoView(mContext)); mComponentTree.attach(); mComponentTree.setSizeSpec(mWidthSpec, mHeightSpec); verify(mListener).onNewLayoutStateReady(mComponentTree); reset(mListener); mComponentTree.measure(mWidthSpec2, mHeightSpec2, new int[] {0, 0}, false); verify(mListener).onNewLayoutStateReady(mComponentTree); }
@Test public void testSetSizeSpec() { ComponentTree componentTree = ComponentTree.create(mContext, mComponent) .build(); componentTree.setSizeSpec(mWidthSpec, mHeightSpec); // Since this happens post creation, it's not in general safe to update the main thread layout // state synchronously, so the result should be in the background layout state postSizeSpecChecks(componentTree, "mBackgroundLayoutState"); }
@Test public void testSetSizeSpecWithOutput() { ComponentTree componentTree = ComponentTree.create(mContext, mComponent) .build(); Size size = new Size(); componentTree.setSizeSpec(mWidthSpec, mHeightSpec, size); assertEquals(SizeSpec.getSize(mWidthSpec), size.width, 0.0); assertEquals(SizeSpec.getSize(mHeightSpec), size.height, 0.0); // Since this happens post creation, it's not in general safe to update the main thread layout // state synchronously, so the result should be in the background layout state postSizeSpecChecks(componentTree, "mBackgroundLayoutState"); }
@Test public void testSetCompatibleSizeSpec() { ComponentTree componentTree = create(mContext, mComponent) .build(); Size size = new Size(); componentTree.setSizeSpec( makeSizeSpec(100, AT_MOST), makeSizeSpec(100, AT_MOST), size); assertEquals(100, size.width, 0.0); assertEquals(100, size.height, 0.0); LayoutState firstLayoutState = componentTree.getBackgroundLayoutState(); assertThat(firstLayoutState).isNotNull(); componentTree.setSizeSpec( makeSizeSpec(100, EXACTLY), makeSizeSpec(100, EXACTLY), size); assertEquals(100, size.width, 0.0); assertEquals(100, size.height, 0.0); assertThat(componentTree.getBackgroundLayoutState()).isEqualTo(firstLayoutState); }
private ComponentTree createComponentTree(boolean useSpy, boolean incMountEnabled, int width, int height) { ComponentTree componentTree = ComponentTree.create(mContext, mComponent) .incrementalMount(incMountEnabled) .layoutDiffing(false) .build(); componentTree.setSizeSpec( SizeSpec.makeSizeSpec(width, EXACTLY), SizeSpec.makeSizeSpec(height, EXACTLY)); return useSpy ? spy(componentTree) : componentTree; }
@Test public void testSetSizeSpecWithOutputWhenAttachedToViewWithSameSpec() { ComponentTree componentTree = ComponentTree.create(mContext, mComponent).build(); componentTree.setLithoView(new LithoView(mContext)); Size size = new Size(); componentTree.measure(mWidthSpec, mHeightSpec, new int[2], false); componentTree.attach(); componentTree.setSizeSpec(mWidthSpec, mHeightSpec, size); assertEquals(SizeSpec.getSize(mWidthSpec), size.width, 0.0); assertEquals(SizeSpec.getSize(mHeightSpec), size.height, 0.0); assertThat(componentTree.hasCompatibleLayout(mWidthSpec, mHeightSpec)).isTrue(); assertThat(componentTree.getRoot()).isEqualTo(mComponent); }
@Test public void testSetSizeSpecWithOutputWhenAttachedToViewWithNewSpec() { ComponentTree componentTree = ComponentTree.create(mContext, mComponent).build(); componentTree.setLithoView(new LithoView(mContext)); Size size = new Size(); componentTree.measure(mWidthSpec2, mHeightSpec2, new int[2], false); componentTree.attach(); componentTree.setSizeSpec(mWidthSpec, mHeightSpec, size); assertEquals(SizeSpec.getSize(mWidthSpec), size.width, 0.0); assertEquals(SizeSpec.getSize(mHeightSpec), size.height, 0.0); assertThat(componentTree.hasCompatibleLayout(mWidthSpec, mHeightSpec)).isTrue(); assertThat(componentTree.getRoot()).isEqualTo(mComponent); }
@Test public void testTransferState() { mComponentTree.updateStateAsync(mTestComponent.getGlobalKey(), new TestStateUpdate(), "test"); mLayoutThreadShadowLooper.runToEndOfTasks(); mComponentTree.setSizeSpec(mWidthSpec, mHeightSpec); assertThat(mTestComponent.getComponentForStateUpdate().getCount()).isEqualTo(INITIAL_COUNT_STATE_VALUE + 1); }
@Test public void testRemountAfterSettingNewRootTwice() { final TestComponent component1 = create(mContext).color(Color.RED).returnSelfInMakeShallowCopy().build(); final TestComponent component2 = create(mContext).returnSelfInMakeShallowCopy().color(Color.BLUE).build(); final LithoView lithoView = new LithoView(mContext); final ComponentTree componentTree = ComponentTree.create(mContext, Column.create(mContext).child(component1).build()).build(); mountComponent( lithoView, componentTree, makeMeasureSpec(100, EXACTLY), makeMeasureSpec(100, EXACTLY)); assertThat(component1.isMounted()).isTrue(); componentTree.setRootAndSizeSpec( Column.create(mContext).child(component2).build(), makeMeasureSpec(50, EXACTLY), makeMeasureSpec(50, EXACTLY)); componentTree.setSizeSpec(makeMeasureSpec(100, EXACTLY), makeMeasureSpec(100, EXACTLY)); assertThat(component2.isMounted()).isTrue(); }
@Test public void testSkipShouldUpdateAndRemountForUnsupportedComponent() { final TestComponent firstComponent = create( mContext, false, true, true, false, false) .build(); final LithoView firstLithoView = mountComponent(mContext, Column.create(mContext).child(firstComponent).build()); assertThat(firstComponent.wasOnMountCalled()).isTrue(); assertThat(firstComponent.wasOnBindCalled()).isTrue(); assertThat(firstComponent.wasOnUnmountCalled()).isFalse(); final TestComponent secondComponent = spy(create(mContext, false, true, true, false, false).build()); doReturn(secondComponent).when(secondComponent).makeShallowCopy(); final ComponentTree secondTree = ComponentTree.create(mContext, Column.create(mContext).child(secondComponent).build()) .build(); secondTree.setSizeSpec(100, 100); mountComponent(firstLithoView, secondTree); verify(secondComponent).makeShallowCopy(); assertThat(secondComponent.wasOnMountCalled()).isTrue(); assertThat(secondComponent.wasOnBindCalled()).isTrue(); assertThat(firstComponent.wasOnUnmountCalled()).isTrue(); }
@Test public void testSetCompatibleSizeSpecWithDifferentRoot() { ComponentTree componentTree = create(mContext, mComponent) .build(); Size size = new Size(); componentTree.setSizeSpec( makeSizeSpec(100, AT_MOST), makeSizeSpec(100, AT_MOST), size); assertEquals(100, size.width, 0.0); assertEquals(100, size.height, 0.0); LayoutState firstLayoutState = componentTree.getBackgroundLayoutState(); assertThat(firstLayoutState).isNotNull(); componentTree.setRootAndSizeSpec( TestDrawableComponent.create(mContext).build(), makeSizeSpec(100, EXACTLY), makeSizeSpec(100, EXACTLY), size); assertNotEquals(firstLayoutState, componentTree.getBackgroundLayoutState()); }
@Test public void testMountUnmountDoesNotSkipShouldUpdateAndRemount() { final TestComponent firstComponent = create(mContext) .unique() .build(); final LithoView firstLithoView = mountComponent(mContext, Column.create(mContext).child(firstComponent).build()); assertThat(firstComponent.wasOnMountCalled()).isTrue(); assertThat(firstComponent.wasOnBindCalled()).isTrue(); assertThat(firstComponent.wasOnUnmountCalled()).isFalse(); final TestComponent secondComponent = create(mContext) .unique() .build(); final ComponentTree secondTree = ComponentTree.create(mContext, Column.create(mContext).child(secondComponent).build()) .build(); secondTree.setSizeSpec(100, 100); final TestComponent thirdComponent = spy(create(mContext).build()); doReturn(thirdComponent).when(thirdComponent).makeShallowCopy(); secondTree.setRoot(Column.create(mContext).child(thirdComponent).build()); mountComponent(firstLithoView, secondTree); verify(thirdComponent).makeShallowCopy(); assertThat(thirdComponent.wasOnMountCalled()).isTrue(); assertThat(thirdComponent.wasOnBindCalled()).isTrue(); assertThat(firstComponent.wasOnUnmountCalled()).isTrue(); }
newComponent, makeMeasureSpec(400, EXACTLY), makeMeasureSpec(400, EXACTLY)); componentTree.setSizeSpec(makeMeasureSpec(400, EXACTLY), makeMeasureSpec(400, EXACTLY));
@Test public void testSetInput() { Component component = TestLayoutComponent.create(mContext) .build(); ComponentTree componentTree = ComponentTree.create(mContext, component) .build(); componentTree.setRoot(mComponent); creationCommonChecks(componentTree); Assert.assertNull(Whitebox.getInternalState(componentTree, "mMainThreadLayoutState")); Assert.assertNull(Whitebox.getInternalState(componentTree, "mBackgroundLayoutState")); componentTree.setSizeSpec(mWidthSpec, mHeightSpec); // Since this happens post creation, it's not in general safe to update the main thread layout // state synchronously, so the result should be in the background layout state postSizeSpecChecks(componentTree, "mBackgroundLayoutState"); }
newComponent, makeMeasureSpec(400, EXACTLY), makeMeasureSpec(400, EXACTLY)); componentTree.setSizeSpec(makeMeasureSpec(400, EXACTLY), makeMeasureSpec(400, EXACTLY));