Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(267)

Unified Diff: LayoutTests/fast/scroll-behavior/scroll-customization/touch-scroll-customization.html

Issue 1057603002: Expose scroll customization for touch to JS (behind REF). (Closed) Base URL: https://chromium.googlesource.com/chromium/blink.git@master
Patch Set: Address haraken's comments. Created 5 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: LayoutTests/fast/scroll-behavior/scroll-customization/touch-scroll-customization.html
diff --git a/LayoutTests/fast/scroll-behavior/scroll-customization/touch-scroll-customization.html b/LayoutTests/fast/scroll-behavior/scroll-customization/touch-scroll-customization.html
new file mode 100644
index 0000000000000000000000000000000000000000..633eb8d62bc326e678870b4aadba4962360a5b23
--- /dev/null
+++ b/LayoutTests/fast/scroll-behavior/scroll-customization/touch-scroll-customization.html
@@ -0,0 +1,315 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>Scroll customization methods are called appropriately.</title>
+<script src="../../../resources/testharness.js"></script>
+<script src="../../../resources/testharnessreport.js"></script>
+<style>
+
+* {
+ margin:0;
+ padding:0;
+}
+
+*::-webkit-scrollbar {
+ width: 0 !important;
+ height: 0 !important;
+}
+
+#a {
+ height:400px;
+ width:400px;
+ overflow:scroll;
+}
+
+#b {
+ height:500px;
+ width:500px;
+ background-color:purple;
+}
+
+#c {
+ height:300px;
+ width:300px;
+ overflow:scroll;
+}
+
+#d {
+ height:400px;
+ width:400px;
+ background-color:green;
+}
+
+body {
+ height:3000px;
+}
+
+</style>
+</head>
+<body>
+
+<div id="a">
+<div id="b">
+<div id="c">
+<div id="d">
+</div>
+</div>
+</div>
+</div>
+
+<script>
+test(function() {
+ assert_true('ScrollState' in window, "'ScrollState' in window");
+}, "These tests only work with scroll customization enabled.");
+
+var originalApplyScrolls = [];
+var originalDistributeScrolls = [];
+var deltas = [-85, -75, -65, -55, -45];
+
+var elements = [
+ document.getElementById("d"),
+ document.getElementById("c"),
+ document.getElementById("b"),
+ document.getElementById("a"),
+ document.scrollingElement];
+
+var scrollableElements = [elements[1], elements[3], elements[4]];
+
+document.scrollingElement.id = "scrollingElement";
+
+for (var i = 0; i < elements.length; ++i) {
+ originalApplyScrolls[i] = elements[i].applyScroll;
+ originalDistributeScrolls[i] = elements[i].distributeScroll;
+}
+
+function reset() {
+ for (var i = 0; i < elements.length; ++i) {
+ var j = i;
+ elements[i].scrollTop = 0;
+ elements[i].unappliedDeltaY = [];
+ elements[i].distributedDeltaY = [];
+ elements[i].numberOfScrollBegins = 0;
+ elements[i].numberOfScrollEnds = 0;
+
+ elements[i].setApplyScroll((function(originalApplyScroll, scrollState) {
+ originalApplyScroll.call(this, scrollState);
+ if (!scrollState.isEnding && !scrollState.isBeginning)
+ this.unappliedDeltaY.push(scrollState.deltaY);
+ }).bind(elements[i], originalApplyScrolls[i]));
+
+ elements[i].setDistributeScroll((function(originalDistributeScroll, scrollState) {
+ if (scrollState.isBeginning)
+ this.numberOfScrollBegins++;
+ else if (scrollState.isEnding)
+ this.numberOfScrollEnds++;
+ else
+ this.distributedDeltaY.push(scrollState.deltaY);
+ originalDistributeScroll.call(this, scrollState);
+ }).bind(elements[i], originalDistributeScrolls[i]));
+ }
+}
+
+function applyDelta(d) {
+ eventSender.gestureScrollBegin(10, 10);
+ eventSender.gestureScrollUpdate(0, d);
+ eventSender.gestureScrollEnd(0, 0);
+}
+
+if ('ScrollState' in window) {
+ test(function() {
+ reset();
+
+ // Scroll five times, with three scrollable elements.
+ var cScrollTop = [85, 100, 100, 100, 100];
+ var aScrollTop = [0, 0, 65, 100, 100];
+ var scrollingElementScrollTop = [0, 0, 0, 0, 45];
+
+ for (var i = 0; i < deltas.length; ++i) {
+ applyDelta(deltas[i]);
+ assert_equals(a.scrollTop, aScrollTop[i], "For id 'a' on step " + i);
+ assert_equals(c.scrollTop, cScrollTop[i], "For id 'c' on step " + i);
+ assert_equals(document.scrollingElement.scrollTop, scrollingElementScrollTop[i], "For scrollingElement on step " + i);
+ }
+ }, "Scroll offsets are modified correctly.");
+
+ test(function() {
+ reset();
+
+ // Scroll five times, with five elements.
+ var unapplied = [
+ // d, the innermost element, never applies any scroll.
+ [-85, -75, -65, -55, -45],
+ // c applies the first two scrolls, and then hits its scroll extents.
+ [0, 0, -65, -55, -45],
+ // b doesn't scroll, and so leaves the same deltas unapplied as c.
+ [0, 0, -65, -55, -45],
+ // a hits its scroll extent on the second last step.
+ [0, 0, 0, 0, -45],
+ // The scrollingElement performs the frame scroll.
+ [0, 0, 0, 0, 0]];
+
+ for (var i = 0; i < deltas.length; ++i)
+ applyDelta(deltas[i]);
+
+ for (var i = 0; i < elements.length; ++i) {
+ var el = elements[i];
+ // Every element sees the same deltas being distributed.
+ assert_array_equals(el.distributedDeltaY, deltas, "distributed delta for " + el.id);
+ assert_array_equals(el.unappliedDeltaY, unapplied[i], "unapplied delta for " + el.id);
+ }
+
+ // Ensure that the document leaves scroll unapplied when appropriate.
+ var documentUnapplied = document.scrollingElement.unappliedDeltaY;
+ applyDelta(-4000);
+ assert_equals(documentUnapplied[documentUnapplied.length - 1], 0);
+ applyDelta(-4000);
+ assert_equals(documentUnapplied[documentUnapplied.length - 1], -4000);
+ }, "Correct amount of delta is consumed.");
+
+ test(function() {
+ reset();
+ // Consume one pixel of delta per call to applyScroll.
+ for (var i = 0; i < elements.length; ++i) {
+ if (scrollableElements.indexOf(elements[i]) == -1)
+ continue;
+ elements[i].setApplyScroll((function(originalApplyScroll, scrollState) {
+ if (scrollState.deltaY !== 0)
+ scrollState.consumeDelta(0, -1);
+ originalApplyScroll.call(this, scrollState);
+ }).bind(elements[i], originalApplyScrolls[i]));
+ }
+ // Scroll five times, with three scrollable elements.
+ // The scroll distance is decreased more the higher up the scroll chain the element is.
+ var cScrollTop = [85 - 1, 100, 100, 100, 100];
+ var aScrollTop = [0, 0, 65 - 2, 100, 100];
+ var scrollingElementScrollTop = [0, 0, 0, 0, 45 - 3];
+
+ for (var i = 0; i < deltas.length; ++i) {
+ applyDelta(deltas[i]);
+ assert_equals(c.scrollTop, cScrollTop[i], "For id 'c' on step " + i);
+ assert_equals(a.scrollTop, aScrollTop[i], "For id 'a' on step " + i);
+ assert_equals(document.scrollingElement.scrollTop, scrollingElementScrollTop[i], "For scrollingElement on step " + i);
+ }
+ }, "Consuming deltas prevents scrolling.");
+
+ test(function() {
+ reset();
+
+ for (var i = 0; i < deltas.length; ++i)
+ applyDelta(deltas[i]);
+ for (var i = 0; i < elements.length; ++i) {
+ assert_equals(elements[i].numberOfScrollBegins, deltas.length, "Incorrect number of begin events for " + elements[i].id);
+ assert_equals(elements[i].numberOfScrollEnds, deltas.length, "Incorrect number of end events for " + elements[i].id);
+ }
+ }, "Correct number of scroll end and begin events observed.");
+
+ test(function() {
+ // toPerform is an array of length 4, specifying whether to
+ // perform method |original| on |element| for scroll begin, first
+ // update, second update and scroll end.
+ function performSomeOf(element, original, toPerform) {
+ var updateCount = 0;
+ return function(scrollState) {
+ if (scrollState.isBeginning && scrollState.isEnding)
+ throw "performSomeOf requires that the scroll not both begin and end";
+
+ var isUpdate = !scrollState.isBeginning && !scrollState.isEnding;
+
+ if ((scrollState.isBeginning && toPerform[0]) ||
+ (scrollState.isEnding && toPerform[3]) ||
+ (isUpdate && updateCount === 0 && toPerform[1]) ||
+ (isUpdate && updateCount > 0 && toPerform[2])) {
+ original.call(element, scrollState);
+ }
+
+ if (isUpdate)
+ updateCount++;
+ };
+ }
+
+ // Generates an array of all arrays of booleans of length n.
+ // e.g. genPermutations(2) =>
+ // [[true, true], [true, false], [false, true], [false, false]].
+ function genPermutations(n) {
+ if (n === 0)
+ return [[]];
+ var perms = genPermutations(n - 1);
+ return perms.map(function(x) {
+ return x.concat([true]);
+ }).concat(perms.map(function(x) {
+ return x.concat([false]);
+ }));
+ }
+
+ function applyDeltaWithTwoUpdates(d) {
+ eventSender.gestureScrollBegin(10, 10);
+ eventSender.gestureScrollUpdate(0, d/2);
+ eventSender.gestureScrollUpdate(0, d/2);
+ eventSender.gestureScrollEnd(0, 0);
+ }
+
+ var scroller = document.scrollingElement;
+
+ for (applyScrollPermutation of genPermutations(4)) {
+ reset();
+ scroller.setApplyScroll(performSomeOf(scroller, scroller.applyScroll, applyScrollPermutation));
+
+ for (distributeScrollPermutation of genPermutations(4)) {
+ scroller.setDistributeScroll(performSomeOf(scroller, scroller.distributeScroll, distributeScrollPermutation));
+ applyDeltaWithTwoUpdates(-50);
+ }
+ }
+ }, "Ensure that any subset of the native scroll methods can be called, without crashing");
+
+ {
+ // NOTE - this async test needs to be run last, as it shares state with the
+ // other tests. If other tests are run after it, they'll modify the state
+ // while this test is still running.
+ var flingTest = async_test("Touchscreen fling doesn't propagate.");
+ reset();
+
+ function assertScrollTops(cTop, aTop, scrollingElementTop, step) {
+ assert_equals(c.scrollTop, cTop, "For id 'c' on step " + step);
+ assert_equals(a.scrollTop, aTop, "For id 'a' on step " + step);
+ assert_equals(document.scrollingElement.scrollTop, scrollingElementTop, "For scrollingElement on step " + step);
+ };
+
+ var frame_actions = [
+ function() {
+ eventSender.gestureFlingStart(10, 10, -1000000, -1000000, "touchscreen");
+ },
+ flingTest.step_func(function() {
+ assertScrollTops(0, 0, 0, 1);
+ }),
+ flingTest.step_func(function() {
+ assertScrollTops(100, 0, 0, 2);
+ }),
+ flingTest.step_func(function() {
+ assertScrollTops(100, 0, 0, 3);
+ }),
+ flingTest.step_func(function() {
+ assertScrollTops(100, 0, 0, 4);
+ flingTest.done();
+ })
+ ]
+
+ function executeFrameActions(frame_actions) {
+ var frame = 0;
+ function raf() {
+ frame_actions[frame]();
+ frame++;
+ if (frame >= frame_actions.length)
+ return;
+ window.requestAnimationFrame(raf);
+ }
+ window.requestAnimationFrame(raf);
+ }
+
+ executeFrameActions(frame_actions);
+ }
+}
+
+</script>
+</body>
+</html>

Powered by Google App Engine
This is Rietveld 408576698