Source code

Revision control

Copy as Markdown

Other Tools

Test Info: Warnings

<!DOCTYPE html>
<!-- TODO(crbug.com/40275057) Fix test for pointer-event-range-input.html?pen.
-->
<title>Pointer dragging behavior on input type='range' </title>
<meta name="variant" content="?touch">
<meta name="variant" content="?mouse">
<script src='/resources/testharness.js'></script>
<script src='/resources/testharnessreport.js'></script>
<script src='/resources/testdriver.js'></script>
<script src='/resources/testdriver-actions.js'></script>
<script src='/resources/testdriver-vendor.js'></script>
<style type='text/css'>
body {
margin: 0;
}
</style>
<div><input type='range' id='slider1' min='0' max='100' step='10'></div>
<div><input type='range' id='slider2' min='0' max='100' step='10' style='touch-action:none;'></div>
<div><input type='range' id='slider3' min='0' max='100' step='10' style='writing-mode:vertical-lr; direction:rtl;'></div>
<script>
"use strict";
const pointerType = location.search.substring(1);
function isMouse() {
return pointerType === 'mouse';
}
function isTouch() {
return pointerType === 'touch';
}
// Verify that a point is on screen.
// (x,y) is relative to the center of the origin element.
function assert_point_within_viewport(x, y, origin) {
const rect = origin.getBoundingClientRect();
const center_point = {
x: rect.x + rect.width / 2,
y: rect.y + rect.height / 2
};
const viewport_point = {
x: (center_point.x - visualViewport.offsetLeft) * visualViewport.scale,
y: (center_point.y - visualViewport.offsetTop) * visualViewport.scale
};
x += viewport_point.x;
y += viewport_point.y;
assert_true(x >= 0 && x <= window.innerWidth,
'x coordinate outside viewport');
assert_true(y >= 0 && y <= window.innerHeight,
'y coordinate outside viewport');
}
// The deltas are relative to the center of the target.
function smoothDrag(delta_x, delta_y, target) {
const eventTarget = document;
const prevent_fling_pause_ms = isTouch() ? 100 : 0;
const x = 0;
const y = 0;
const end_x = Math.round(delta_x);
const end_y = Math.round(delta_y);
assert_point_within_viewport(end_x, end_y, target);
// Expect a pointerup or pointercancel event depending on whether scrolling
// actually took place.
return new Promise(resolve => {
const pointerPromise = new Promise(resolve => {
const pointerListener = (event) => {
eventTarget.removeEventListener('pointerup', pointerListener);
eventTarget.removeEventListener('pointercancel', pointerListener);
resolve(event.type);
};
eventTarget.addEventListener('pointerup', pointerListener);
eventTarget.addEventListener('pointercancel', pointerListener);
});
const actionPromise = new test_driver.Actions()
.addPointer("pointer1", pointerType)
.pointerMove(x, y, { origin: target })
.pointerDown({button: 0/*Left*/})
.pointerMove(end_x, end_y, { origin: target })
.pause(prevent_fling_pause_ms)
.pointerUp({button: 0 /*Left*/})
.send();
Promise.all([actionPromise, pointerPromise]).then(responses => {
resolve(responses[1]);
});
});
}
function forceLayoutUpdate() {
document.body.offsetTop;
}
const slider1 = document.getElementById('slider1');
const slider2 = document.getElementById('slider2');
const slider3 = document.getElementById('slider3');
function resetPage() {
slider1.value = 50;
slider2.value = 50;
slider3.value = 50;
}
const isMac = navigator.platform.indexOf('Mac') == 0;
if (isMac && isTouch()) {
// Mac devices do not support touch.
testNothing();
} else {
forceLayoutUpdate();
promise_test(async t => {
resetPage();
assert_equals(parseInt(slider1.value), 50, "Slider1's initial value");
// Perform a left drag from the center of the slider.
const gestureCompletionEventType =
await smoothDrag(-slider1.clientWidth / 2, 0, slider1);
assert_equals(gestureCompletionEventType, 'pointerup',
"The gesture is completed with 'pointerup'");
assert_equals(parseInt(slider1.value), 0,
"Should set slider1's value to 0");
}, 'Horizontal drag on a horizontal slider.');
promise_test(async t => {
resetPage();
assert_equals(parseInt(slider1.value), 50, "Slider1's initial value");
// Perform a down drag from the center of the slider.
const gestureCompletionEventType =
await smoothDrag(0, slider1.clientWidth, slider1);
assert_equals(parseInt(slider1.value), 50,
"Should not change slider1's value.");
// Don't assert gestureCompletionEventType value. Depending on the UA, the
// gesture may result in scroll. In this case gestureCompletionEventType
// is 'pointercancel'.
}, 'Vertical drag on a horizontal slider.');
promise_test(async t => {
resetPage();
assert_equals(parseInt(slider2.value), 50, "Slider2's initial value");
// Perform a down drag from the center of the slider.
const gestureCompletionEventType =
await smoothDrag(0, slider2.clientWidth, slider2);
assert_equals(gestureCompletionEventType, 'pointerup',
"The gesture is completed with 'pointerup'");
assert_equals(parseInt(slider2.value), 50,
"Should not change slider2's value.");
}, 'Vertical drag on a horizontal slider with touch-action:none.');
promise_test(async t => {
resetPage();
assert_equals(parseInt(slider3.value), 50, "Slider3's initial value.");
// Perform an up drag from the center of the slider.
const gestureCompletionEventType =
await smoothDrag(0, -slider3.clientHeight / 2, slider3);
assert_equals(gestureCompletionEventType, 'pointerup',
"The gesture is completed with 'pointerup'");
assert_equals(parseInt(slider3.value), 100,
"Should set slider3' value to 100.");
}, 'Vertical drag on a vertical slider.');
promise_test(async t => {
resetPage();
assert_equals(parseInt(slider3.value), 50, "Slider3's initial value.");
// Perform a right drag from the center of the slider.
const gestureCompletionEventType =
await smoothDrag(slider3.clientHeight, 0, slider3);
assert_equals(parseInt(slider3.value), 50,
"Should not change slider3' value.");
// Don't assert gestureCompletionEventType value. Depending on the UA, the
// gesture may result in scroll. In this case gestureCompletionEventType
// is 'pointercancel'.
}, 'Horizontal drag on a vertical slider.');
}
function testNothing() {
test(() => {}, 'Empty test for MacOS.');
}
</script>