/* * Copyright (c) 2015-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.drawee.view; import android.graphics.drawable.Drawable; import com.facebook.drawee.drawable.DrawableTestUtils; import com.facebook.drawee.interfaces.DraweeHierarchy; import com.facebook.drawee.interfaces.DraweeController; import com.facebook.drawee.testing.DraweeMocks; import com.facebook.testing.robolectric.v2.WithTestDefaultsRunner; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.InOrder; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertSame; import static org.mockito.Mockito.inOrder; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; @RunWith(WithTestDefaultsRunner.class) public class DraweeHolderTest { private DraweeHolder mDraweeHolder; private Drawable mTopLevelDrawable; private DraweeHierarchy mDraweeHierarchy; private DraweeController mController; private InOrder mInOrderVerifier; @Before public void setUp() { mTopLevelDrawable = DrawableTestUtils.mockDrawable(); mDraweeHierarchy = DraweeMocks.mockDraweeHierarchyOf(mTopLevelDrawable); mController = DraweeMocks.mockController(); mDraweeHolder = new DraweeHolder(mDraweeHierarchy); mInOrderVerifier = inOrder(mController); } @Test public void testOverrideControllerHierarchy() { DraweeHierarchy otherHierarchy = mock(DraweeHierarchy.class); mController.setHierarchy(otherHierarchy); assertSame(otherHierarchy, mController.getHierarchy()); mDraweeHolder.setController(mController); assertSame(mController, mDraweeHolder.getController()); assertSame(mDraweeHierarchy, mDraweeHolder.getHierarchy()); assertSame(mDraweeHierarchy, mController.getHierarchy()); } @Test public void testSetControllerWithoutHierarchy() { mDraweeHolder.setController(mController); assertSame(mController, mDraweeHolder.getController()); assertSame(mDraweeHierarchy, mDraweeHolder.getHierarchy()); assertSame(mDraweeHierarchy, mController.getHierarchy()); } @Test public void testClearControllerKeepsHierarchy() { mDraweeHolder.setController(mController); mDraweeHolder.setController(null); assertSame(mDraweeHierarchy, mDraweeHolder.getHierarchy()); assertNull(mDraweeHolder.getController()); assertNull(mController.getHierarchy()); } @Test public void testNewControllerKeepsHierarchy() { mDraweeHolder.setController(mController); assertSame(mDraweeHierarchy, mDraweeHolder.getHierarchy()); DraweeController another = DraweeMocks.mockController(); mDraweeHolder.setController(another); assertSame(mDraweeHierarchy, mDraweeHolder.getHierarchy()); assertSame(another, mDraweeHolder.getController()); assertNull(mController.getHierarchy()); assertSame(mDraweeHierarchy, another.getHierarchy()); } @Test public void testLifecycle() { mDraweeHolder.setController(mController); mDraweeHolder.onAttach(); mDraweeHolder.onDetach(); verify(mController).onAttach(); verify(mController).onDetach(); } @Test public void testSetControllerWhenAlreadyAttached() { mDraweeHolder.onAttach(); mDraweeHolder.setController(mController); mDraweeHolder.onDetach(); verify(mController).onAttach(); verify(mController).onDetach(); } @Test public void testSetNullController() { mDraweeHolder.setController(null); mDraweeHolder.onAttach(); mDraweeHolder.onDetach(); mDraweeHolder.onAttach(); } /** There are 8 possible state transitions with two variables * 1. (visible, unattached) -> (visible, attached) * 2. (visible, attached) -> (invisible, attached) * 3. (invisible, attached) -> (invisible, unattached) * 4. (invisible, unattached) -> (visible, unattached) * 5. (visible, unattached) -> (invisible, unattached) * 6. (invisible, unattached) -> (invisible, attached) * 7. (invisible, attached) -> (visible, attached) * 8. (visible, attached) -> (visible, unattached) */ @Test public void testVisibilityStateTransitions() { boolean restart = true; // Initial state (mIsVisible, !mIsHolderAttached) mDraweeHolder.setController(mController); verifyControllerLifecycleCalls(0, 0); /** 1 */ mDraweeHolder.onAttach(); verifyControllerLifecycleCalls(1, 0); /** 2 */ mTopLevelDrawable.setVisible(false, restart); verifyControllerLifecycleCalls(0, 1); /** 3 */ mDraweeHolder.onDetach(); verifyControllerLifecycleCalls(0, 0); /** 4 */ mTopLevelDrawable.setVisible(true, restart); verifyControllerLifecycleCalls(0, 0); /** 5 */ mTopLevelDrawable.setVisible(false, restart); verifyControllerLifecycleCalls(0, 0); /** 6 */ mDraweeHolder.onAttach(); verifyControllerLifecycleCalls(0, 0); /** 7 */ mTopLevelDrawable.setVisible(true, restart); verifyControllerLifecycleCalls(1, 0); /** 8 */ mDraweeHolder.onDetach(); verifyControllerLifecycleCalls(0, 1); } private void verifyControllerLifecycleCalls(int numOnAttach, int numOnDetatch) { mInOrderVerifier.verify(mController, times(numOnAttach)).onAttach(); mInOrderVerifier.verify(mController, times(numOnDetatch)).onDetach(); } }