blob: 49c25977f3f34562157b9304a66b11ba3b6b1ac2 [file] [log] [blame]
// Copyright 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
package org.chromium.android_webview.robolectric;
import android.graphics.Rect;
import android.support.test.filters.SmallTest;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.robolectric.annotation.Config;
import org.chromium.android_webview.AwScrollOffsetManager;
import org.chromium.base.test.util.Feature;
import org.chromium.testing.local.LocalRobolectricTestRunner;
/**
* Integration tests for ScrollOffsetManager.
*/
@RunWith(LocalRobolectricTestRunner.class)
@Config(manifest = Config.NONE)
public class AwScrollOffsetManagerTest {
private static class TestScrollOffsetManagerDelegate implements AwScrollOffsetManager.Delegate {
private int mOverScrollDeltaX;
private int mOverScrollDeltaY;
private int mOverScrollCallCount;
private int mScrollX;
private int mScrollY;
private int mNativeScrollX;
private int mNativeScrollY;
private int mInvalidateCount;
public int getOverScrollDeltaX() {
return mOverScrollDeltaX;
}
public int getOverScrollDeltaY() {
return mOverScrollDeltaY;
}
public int getOverScrollCallCount() {
return mOverScrollCallCount;
}
public int getScrollX() {
return mScrollX;
}
public int getScrollY() {
return mScrollY;
}
public int getNativeScrollX() {
return mNativeScrollX;
}
public int getNativeScrollY() {
return mNativeScrollY;
}
public int getInvalidateCount() {
return mInvalidateCount;
}
@Override
public void overScrollContainerViewBy(int deltaX, int deltaY, int scrollX, int scrollY,
int scrollRangeX, int scrollRangeY, boolean isTouchEvent) {
mOverScrollDeltaX = deltaX;
mOverScrollDeltaY = deltaY;
mOverScrollCallCount += 1;
}
@Override
public void scrollContainerViewTo(int x, int y) {
mScrollX = x;
mScrollY = y;
}
@Override
public void scrollNativeTo(int x, int y) {
mNativeScrollX = x;
mNativeScrollY = y;
}
@Override
public int getContainerViewScrollX() {
return mScrollX;
}
@Override
public int getContainerViewScrollY() {
return mScrollY;
}
@Override
public void invalidate() {
mInvalidateCount += 1;
}
@Override
public void cancelFling() {}
@Override
public void smoothScroll(int targetX, int targetY, long durationMs) {}
}
private void simulateScrolling(AwScrollOffsetManager offsetManager,
TestScrollOffsetManagerDelegate delegate, int scrollX, int scrollY) {
// Scrolling is a two-phase action. First we ask the manager to scroll
int callCount = delegate.getOverScrollCallCount();
offsetManager.scrollContainerViewTo(scrollX, scrollY);
// The manager then asks the delegate to overscroll the view.
Assert.assertEquals(callCount + 1, delegate.getOverScrollCallCount());
Assert.assertEquals(scrollX, delegate.getOverScrollDeltaX() + delegate.getScrollX());
Assert.assertEquals(scrollY, delegate.getOverScrollDeltaY() + delegate.getScrollY());
// As a response to that the menager expects the view to call back with the new scroll.
offsetManager.onContainerViewOverScrolled(scrollX, scrollY, false, false);
}
private void simlateOverScrollPropagation(
AwScrollOffsetManager offsetManager, TestScrollOffsetManagerDelegate delegate) {
Assert.assertTrue(delegate.getOverScrollCallCount() > 0);
offsetManager.onContainerViewOverScrolled(
delegate.getOverScrollDeltaX() + delegate.getScrollX(),
delegate.getOverScrollDeltaY() + delegate.getScrollY(), false, false);
}
@Test
@SmallTest
@Feature({"AndroidWebView"})
public void testWhenContentSizeMatchesView() {
TestScrollOffsetManagerDelegate delegate = new TestScrollOffsetManagerDelegate();
AwScrollOffsetManager offsetManager = new AwScrollOffsetManager(delegate);
final int width = 132;
final int height = 212;
final int scrollX = 11;
final int scrollY = 13;
offsetManager.setMaxScrollOffset(0, 0);
offsetManager.setContainerViewSize(width, height);
Assert.assertEquals(width, offsetManager.computeHorizontalScrollRange());
Assert.assertEquals(height, offsetManager.computeVerticalScrollRange());
// Since the view size and contents size are equal no scrolling should be possible.
Assert.assertEquals(0, offsetManager.computeMaximumHorizontalScrollOffset());
Assert.assertEquals(0, offsetManager.computeMaximumVerticalScrollOffset());
// Scrolling should generate overscroll but not update the scroll offset.
simulateScrolling(offsetManager, delegate, scrollX, scrollY);
Assert.assertEquals(scrollX, delegate.getOverScrollDeltaX());
Assert.assertEquals(scrollY, delegate.getOverScrollDeltaY());
Assert.assertEquals(0, delegate.getScrollX());
Assert.assertEquals(0, delegate.getScrollY());
Assert.assertEquals(0, delegate.getNativeScrollX());
Assert.assertEquals(0, delegate.getNativeScrollY());
// Scrolling to 0,0 should result in no deltas.
simulateScrolling(offsetManager, delegate, 0, 0);
Assert.assertEquals(0, delegate.getOverScrollDeltaX());
Assert.assertEquals(0, delegate.getOverScrollDeltaY());
// Negative scrolling should result in negative deltas but no scroll offset update.
simulateScrolling(offsetManager, delegate, -scrollX, -scrollY);
Assert.assertEquals(-scrollX, delegate.getOverScrollDeltaX());
Assert.assertEquals(-scrollY, delegate.getOverScrollDeltaY());
Assert.assertEquals(0, delegate.getScrollX());
Assert.assertEquals(0, delegate.getScrollY());
Assert.assertEquals(0, delegate.getNativeScrollX());
Assert.assertEquals(0, delegate.getNativeScrollY());
}
private static final int VIEW_WIDTH = 211;
private static final int VIEW_HEIGHT = 312;
private static final int MAX_HORIZONTAL_OFFSET = 757;
private static final int MAX_VERTICAL_OFFSET = 127;
private static final int CONTENT_WIDTH = VIEW_WIDTH + MAX_HORIZONTAL_OFFSET;
private static final int CONTENT_HEIGHT = VIEW_HEIGHT + MAX_VERTICAL_OFFSET;
@Test
@SmallTest
@Feature({"AndroidWebView"})
public void testScrollRangeAndMaxOffset() {
TestScrollOffsetManagerDelegate delegate = new TestScrollOffsetManagerDelegate();
AwScrollOffsetManager offsetManager = new AwScrollOffsetManager(delegate);
offsetManager.setMaxScrollOffset(MAX_HORIZONTAL_OFFSET, MAX_VERTICAL_OFFSET);
offsetManager.setContainerViewSize(VIEW_WIDTH, VIEW_HEIGHT);
Assert.assertEquals(CONTENT_WIDTH, offsetManager.computeHorizontalScrollRange());
Assert.assertEquals(CONTENT_HEIGHT, offsetManager.computeVerticalScrollRange());
Assert.assertEquals(
MAX_HORIZONTAL_OFFSET, offsetManager.computeMaximumHorizontalScrollOffset());
Assert.assertEquals(
MAX_VERTICAL_OFFSET, offsetManager.computeMaximumVerticalScrollOffset());
// Scrolling beyond the maximum should be clamped.
final int scrollX = MAX_HORIZONTAL_OFFSET + 10;
final int scrollY = MAX_VERTICAL_OFFSET + 11;
simulateScrolling(offsetManager, delegate, scrollX, scrollY);
Assert.assertEquals(scrollX, delegate.getOverScrollDeltaX());
Assert.assertEquals(scrollY, delegate.getOverScrollDeltaY());
Assert.assertEquals(MAX_HORIZONTAL_OFFSET, delegate.getScrollX());
Assert.assertEquals(MAX_VERTICAL_OFFSET, delegate.getScrollY());
Assert.assertEquals(MAX_HORIZONTAL_OFFSET, delegate.getNativeScrollX());
Assert.assertEquals(MAX_VERTICAL_OFFSET, delegate.getNativeScrollY());
// Scrolling to negative coordinates should be clamped back to 0,0.
simulateScrolling(offsetManager, delegate, -scrollX, -scrollY);
Assert.assertEquals(0, delegate.getScrollX());
Assert.assertEquals(0, delegate.getScrollY());
Assert.assertEquals(0, delegate.getNativeScrollX());
Assert.assertEquals(0, delegate.getNativeScrollY());
// The onScrollChanged method is callable by third party code and should also be clamped
offsetManager.onContainerViewScrollChanged(scrollX, scrollY);
Assert.assertEquals(MAX_HORIZONTAL_OFFSET, delegate.getNativeScrollX());
Assert.assertEquals(MAX_VERTICAL_OFFSET, delegate.getNativeScrollY());
offsetManager.onContainerViewScrollChanged(-scrollX, -scrollY);
Assert.assertEquals(0, delegate.getNativeScrollX());
Assert.assertEquals(0, delegate.getNativeScrollY());
}
@Test
@SmallTest
@Feature({"AndroidWebView"})
public void testDelegateCanOverrideScroll() {
final int overrideScrollX = 10;
final int overrideScrollY = 10;
TestScrollOffsetManagerDelegate delegate = new TestScrollOffsetManagerDelegate() {
@Override
public int getContainerViewScrollX() {
return overrideScrollX;
}
@Override
public int getContainerViewScrollY() {
return overrideScrollY;
}
};
AwScrollOffsetManager offsetManager = new AwScrollOffsetManager(delegate);
offsetManager.setMaxScrollOffset(MAX_HORIZONTAL_OFFSET, MAX_VERTICAL_OFFSET);
offsetManager.setContainerViewSize(VIEW_WIDTH, VIEW_HEIGHT);
offsetManager.onContainerViewOverScrolled(0, 0, false, false);
Assert.assertEquals(overrideScrollX, delegate.getNativeScrollX());
Assert.assertEquals(overrideScrollY, delegate.getNativeScrollY());
}
@Test
@SmallTest
@Feature({"AndroidWebView"})
public void testDelegateOverridenScrollsDontExceedBounds() {
final int overrideScrollX = MAX_HORIZONTAL_OFFSET + 10;
final int overrideScrollY = MAX_VERTICAL_OFFSET + 20;
TestScrollOffsetManagerDelegate delegate = new TestScrollOffsetManagerDelegate() {
@Override
public int getContainerViewScrollX() {
return overrideScrollX;
}
@Override
public int getContainerViewScrollY() {
return overrideScrollY;
}
};
AwScrollOffsetManager offsetManager = new AwScrollOffsetManager(delegate);
offsetManager.setMaxScrollOffset(MAX_HORIZONTAL_OFFSET, MAX_VERTICAL_OFFSET);
offsetManager.setContainerViewSize(VIEW_WIDTH, VIEW_HEIGHT);
offsetManager.onContainerViewOverScrolled(0, 0, false, false);
Assert.assertEquals(MAX_HORIZONTAL_OFFSET, delegate.getNativeScrollX());
Assert.assertEquals(MAX_VERTICAL_OFFSET, delegate.getNativeScrollY());
}
@Test
@SmallTest
@Feature({"AndroidWebView"})
public void testScrollContainerViewTo() {
TestScrollOffsetManagerDelegate delegate = new TestScrollOffsetManagerDelegate();
AwScrollOffsetManager offsetManager = new AwScrollOffsetManager(delegate);
final int scrollX = 31;
final int scrollY = 41;
offsetManager.setMaxScrollOffset(MAX_HORIZONTAL_OFFSET, MAX_VERTICAL_OFFSET);
offsetManager.setContainerViewSize(VIEW_WIDTH, VIEW_HEIGHT);
Assert.assertEquals(0, delegate.getOverScrollDeltaX());
Assert.assertEquals(0, delegate.getOverScrollDeltaY());
int callCount = delegate.getOverScrollCallCount();
offsetManager.scrollContainerViewTo(scrollX, scrollY);
Assert.assertEquals(callCount + 1, delegate.getOverScrollCallCount());
Assert.assertEquals(scrollX, delegate.getOverScrollDeltaX());
Assert.assertEquals(scrollY, delegate.getOverScrollDeltaY());
}
@Test
@SmallTest
@Feature({"AndroidWebView"})
public void testOnContainerViewOverScrolled() {
TestScrollOffsetManagerDelegate delegate = new TestScrollOffsetManagerDelegate();
AwScrollOffsetManager offsetManager = new AwScrollOffsetManager(delegate);
final int scrollX = 31;
final int scrollY = 41;
offsetManager.setMaxScrollOffset(MAX_HORIZONTAL_OFFSET, MAX_VERTICAL_OFFSET);
offsetManager.setContainerViewSize(VIEW_WIDTH, VIEW_HEIGHT);
Assert.assertEquals(0, delegate.getScrollX());
Assert.assertEquals(0, delegate.getScrollY());
Assert.assertEquals(0, delegate.getNativeScrollX());
Assert.assertEquals(0, delegate.getNativeScrollY());
offsetManager.onContainerViewOverScrolled(scrollX, scrollY, false, false);
Assert.assertEquals(scrollX, delegate.getScrollX());
Assert.assertEquals(scrollY, delegate.getScrollY());
Assert.assertEquals(scrollX, delegate.getNativeScrollX());
Assert.assertEquals(scrollY, delegate.getNativeScrollY());
}
@Test
@SmallTest
@Feature({"AndroidWebView"})
public void testDefersScrollUntilTouchEnd() {
TestScrollOffsetManagerDelegate delegate = new TestScrollOffsetManagerDelegate();
AwScrollOffsetManager offsetManager = new AwScrollOffsetManager(delegate);
final int scrollX = 31;
final int scrollY = 41;
offsetManager.setMaxScrollOffset(MAX_HORIZONTAL_OFFSET, MAX_VERTICAL_OFFSET);
offsetManager.setContainerViewSize(VIEW_WIDTH, VIEW_HEIGHT);
offsetManager.setProcessingTouchEvent(true);
offsetManager.onContainerViewOverScrolled(scrollX, scrollY, false, false);
Assert.assertEquals(scrollX, delegate.getScrollX());
Assert.assertEquals(scrollY, delegate.getScrollY());
Assert.assertEquals(0, delegate.getNativeScrollX());
Assert.assertEquals(0, delegate.getNativeScrollY());
offsetManager.setProcessingTouchEvent(false);
Assert.assertEquals(scrollX, delegate.getScrollX());
Assert.assertEquals(scrollY, delegate.getScrollY());
Assert.assertEquals(scrollX, delegate.getNativeScrollX());
Assert.assertEquals(scrollY, delegate.getNativeScrollY());
}
@Test
@SmallTest
@Feature({"AndroidWebView"})
public void testRequestChildRectangleOnScreenDontScrollIfAlreadyThere() {
TestScrollOffsetManagerDelegate delegate = new TestScrollOffsetManagerDelegate();
AwScrollOffsetManager offsetManager = new AwScrollOffsetManager(delegate);
offsetManager.setMaxScrollOffset(MAX_HORIZONTAL_OFFSET, MAX_VERTICAL_OFFSET);
offsetManager.setContainerViewSize(VIEW_WIDTH, VIEW_HEIGHT);
offsetManager.requestChildRectangleOnScreen(
0, 0, new Rect(0, 0, VIEW_WIDTH / 4, VIEW_HEIGHT / 4), true);
Assert.assertEquals(0, delegate.getOverScrollDeltaX());
Assert.assertEquals(0, delegate.getOverScrollDeltaY());
Assert.assertEquals(0, delegate.getScrollX());
Assert.assertEquals(0, delegate.getScrollY());
offsetManager.requestChildRectangleOnScreen(3 * VIEW_WIDTH / 4, 3 * VIEW_HEIGHT / 4,
new Rect(0, 0, VIEW_WIDTH / 4, VIEW_HEIGHT / 4), true);
Assert.assertEquals(0, delegate.getOverScrollDeltaX());
Assert.assertEquals(0, delegate.getOverScrollDeltaY());
Assert.assertEquals(0, delegate.getScrollX());
Assert.assertEquals(0, delegate.getScrollY());
}
@Test
@SmallTest
@Feature({"AndroidWebView"})
public void testRequestChildRectangleOnScreenScrollToBottom() {
TestScrollOffsetManagerDelegate delegate = new TestScrollOffsetManagerDelegate();
AwScrollOffsetManager offsetManager = new AwScrollOffsetManager(delegate);
final int rectWidth = 2;
final int rectHeight = 3;
offsetManager.setMaxScrollOffset(MAX_HORIZONTAL_OFFSET, MAX_VERTICAL_OFFSET);
offsetManager.setContainerViewSize(VIEW_WIDTH, VIEW_HEIGHT);
offsetManager.requestChildRectangleOnScreen(CONTENT_WIDTH - rectWidth,
CONTENT_HEIGHT - rectHeight, new Rect(0, 0, rectWidth, rectHeight), true);
simlateOverScrollPropagation(offsetManager, delegate);
Assert.assertEquals(MAX_HORIZONTAL_OFFSET, delegate.getOverScrollDeltaX());
Assert.assertEquals(
CONTENT_HEIGHT - rectHeight - VIEW_HEIGHT / 3, delegate.getOverScrollDeltaY());
Assert.assertEquals(MAX_HORIZONTAL_OFFSET, delegate.getScrollX());
Assert.assertEquals(MAX_VERTICAL_OFFSET, delegate.getScrollY());
}
@Test
@SmallTest
@Feature({"AndroidWebView"})
public void testRequestChildRectangleOnScreenScrollToBottomLargeRect() {
TestScrollOffsetManagerDelegate delegate = new TestScrollOffsetManagerDelegate();
AwScrollOffsetManager offsetManager = new AwScrollOffsetManager(delegate);
final int rectWidth = VIEW_WIDTH;
final int rectHeight = VIEW_HEIGHT;
offsetManager.setMaxScrollOffset(MAX_HORIZONTAL_OFFSET, MAX_VERTICAL_OFFSET);
offsetManager.setContainerViewSize(VIEW_WIDTH, VIEW_HEIGHT);
offsetManager.requestChildRectangleOnScreen(CONTENT_WIDTH - rectWidth,
CONTENT_HEIGHT - rectHeight, new Rect(0, 0, rectWidth, rectHeight), true);
simlateOverScrollPropagation(offsetManager, delegate);
Assert.assertEquals(MAX_HORIZONTAL_OFFSET, delegate.getOverScrollDeltaX());
Assert.assertEquals(MAX_VERTICAL_OFFSET, delegate.getOverScrollDeltaY());
Assert.assertEquals(MAX_HORIZONTAL_OFFSET, delegate.getScrollX());
Assert.assertEquals(MAX_VERTICAL_OFFSET, delegate.getScrollY());
}
@Test
@SmallTest
@Feature({"AndroidWebView"})
public void testRequestChildRectangleOnScreenScrollToTop() {
TestScrollOffsetManagerDelegate delegate = new TestScrollOffsetManagerDelegate();
AwScrollOffsetManager offsetManager = new AwScrollOffsetManager(delegate);
final int rectWidth = 2;
final int rectHeight = 3;
offsetManager.setMaxScrollOffset(MAX_HORIZONTAL_OFFSET, MAX_VERTICAL_OFFSET);
offsetManager.setContainerViewSize(VIEW_WIDTH, VIEW_HEIGHT);
simulateScrolling(
offsetManager, delegate, CONTENT_WIDTH - VIEW_WIDTH, CONTENT_HEIGHT - VIEW_HEIGHT);
offsetManager.requestChildRectangleOnScreen(
0, 0, new Rect(0, 0, rectWidth, rectHeight), true);
simlateOverScrollPropagation(offsetManager, delegate);
Assert.assertEquals(-CONTENT_WIDTH + VIEW_WIDTH, delegate.getOverScrollDeltaX());
Assert.assertEquals(-CONTENT_HEIGHT + VIEW_HEIGHT, delegate.getOverScrollDeltaY());
Assert.assertEquals(0, delegate.getScrollX());
Assert.assertEquals(0, delegate.getScrollX());
}
}