// Copyright 2018 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
package org.chromium.content.browser.selection;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.anyFloat;
import static org.mockito.Mockito.inOrder;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.when;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InOrder;
import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
import org.robolectric.annotation.Config;
import org.robolectric.shadows.ShadowLog;
import org.chromium.base.test.BaseRobolectricTestRunner;
import org.chromium.base.test.util.Feature;
/** Unit tests for MagnifierAnimator. */
@RunWith(BaseRobolectricTestRunner.class)
@Config(manifest = Config.NONE)
public class MagnifierAnimatorTest {
private MagnifierWrapper mMagnifier;
private MagnifierAnimator mAnimator;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
ShadowLog.stream = System.out;
mMagnifier = Mockito.mock(MagnifierWrapper.class);
when(mMagnifier.isAvailable()).thenReturn(true);
mAnimator = new MagnifierAnimator(mMagnifier);
}
@Test
@Feature({"Selection", "TextSelectionMagnifier"})
public void testNormalFlow() {
InOrder order = inOrder(mMagnifier);
// Start to move magnifier.
mAnimator.handleDragStartedOrMoved(10.f, 10.f);
order.verify(mMagnifier).show(10.f, 10.f);
assertFalse("Animator shouldn't run before we change position", isAnimatorRunning());
// Second move doesn't change y-coordinate.
mAnimator.handleDragStartedOrMoved(11.f, 10.f);
order.verify(mMagnifier).show(11.f, 10.f);
// Change y-coordinate. Should trigger animator.
mAnimator.handleDragStartedOrMoved(11.f, 15.f);
assertTrue("Animator should started to run", isAnimatorRunning());
for (int i = 0; i <= 10; ++i) {
final float fraction = 0.1f * i;
setAnimatorCurrentFraction(fraction);
}
order.verify(mMagnifier).show(11.f, 15.f);
mAnimator.handleDragStopped();
order.verify(mMagnifier).dismiss();
assertFalse("Animator should be cancelled", isAnimatorRunning());
}
@Test
@Feature({"Selection", "TextSelectionMagnifier"})
public void testTwoConsecutiveYMoves() {
InOrder order = inOrder(mMagnifier);
// Start to move magnifier.
mAnimator.handleDragStartedOrMoved(10.f, 10.f);
order.verify(mMagnifier).show(10.f, 10.f);
assertFalse("Animator shouldn't run before we change position", isAnimatorRunning());
// Change y-coordinate. Should trigger animator.
mAnimator.handleDragStartedOrMoved(11.f, 15.f);
order.verify(mMagnifier).show(10.f, 10.f);
assertTrue("Animator should started to run", isAnimatorRunning());
float currentX = 0.f;
float currentY = 0.f;
// Animation running.
for (int i = 0; i < 5; ++i) {
final float fraction = 0.1f * i;
currentX = currentValue(10.f, 11.f, fraction);
currentY = currentValue(10.f, 15.f, fraction);
setAnimatorCurrentFraction(fraction);
order.verify(mMagnifier).show(currentX, currentY);
}
assertTrue("Animator should still run", isAnimatorRunning());
mAnimator.handleDragStartedOrMoved(13.f, 20.f);
order.verify(mMagnifier).show(currentX, currentY);
assertTrue("Animator should started to run again", isAnimatorRunning());
for (int i = 0; i <= 10; ++i) {
final float fraction = 0.1f * i;
setAnimatorCurrentFraction(fraction);
}
order.verify(mMagnifier).show(13.f, 20.f);
order.verify(mMagnifier, never()).show(11.f, 15.f);
}
@Test
@Feature({"Selection", "TextSelectionMagnifier"})
public void testCancelMagnifierDuringAnimation() {
InOrder order = inOrder(mMagnifier);
// Start to move magnifier.
mAnimator.handleDragStartedOrMoved(10.f, 10.f);
order.verify(mMagnifier).show(10.f, 10.f);
assertFalse("Animator shouldn't run before we change position", isAnimatorRunning());
// Change y-coordinate. Should trigger animator.
mAnimator.handleDragStartedOrMoved(11.f, 15.f);
// The previous end point is our current start point.
order.verify(mMagnifier).show(10.f, 10.f);
assertTrue("Animator should started to run", isAnimatorRunning());
// Animation running.
for (int i = 0; i < 5; ++i) {
final float fraction = 0.1f * i;
final float currentX = currentValue(10.f, 11.f, fraction);
final float currentY = currentValue(10.f, 15.f, fraction);
setAnimatorCurrentFraction(fraction);
order.verify(mMagnifier).show(currentX, currentY);
}
mAnimator.handleDragStopped();
order.verify(mMagnifier, never()).show(anyFloat(), anyFloat());
order.verify(mMagnifier).dismiss();
assertFalse("Animator should be cancelled", isAnimatorRunning());
}
private boolean isAnimatorRunning() {
return mAnimator.getValueAnimatorForTesting().isRunning();
}
private void setAnimatorCurrentFraction(float fraction) {
mAnimator.getValueAnimatorForTesting().setCurrentFraction(fraction);
}
private float currentValue(float start, float target, float fraction) {
return start + (target - start) * fraction;
}
}