diff options
Diffstat (limited to 'dom/html/test/forms/test_input_range_mouse_and_touch_events.html')
-rw-r--r-- | dom/html/test/forms/test_input_range_mouse_and_touch_events.html | 227 |
1 files changed, 227 insertions, 0 deletions
diff --git a/dom/html/test/forms/test_input_range_mouse_and_touch_events.html b/dom/html/test/forms/test_input_range_mouse_and_touch_events.html new file mode 100644 index 0000000000..92cd1b3095 --- /dev/null +++ b/dom/html/test/forms/test_input_range_mouse_and_touch_events.html @@ -0,0 +1,227 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=846380 +--> +<head> + <title>Test mouse and touch events for range</title> + <script src="/tests/SimpleTest/SimpleTest.js"></script> + <script src="/tests/SimpleTest/EventUtils.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> + <meta charset="UTF-8"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> + <style> + /* synthesizeMouse and synthesizeFunc uses getBoundingClientRect. We set + * the following properties to avoid fractional values in the rect returned + * by getBoundingClientRect in order to avoid rounding that would occur + * when event coordinates are internally converted to be relative to the + * top-left of the element. (Such rounding would make it difficult to + * predict exactly what value the input should take on for events at + * certain coordinates.) + */ + input { margin: 0 ! important; width: 200px ! important; } + </style> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=846380">Mozilla Bug 846380</a> +<p id="display"></p> +<div id="content"> + <input id="range" type="range"> +</div> +<pre id="test"> +<script type="application/javascript"> + +/** + * Test for Bug 846380 + * This test checks how the value of <input type=range> changes in response to + * various mouse and touch events. + **/ +SimpleTest.waitForExplicitFinish(); +SimpleTest.waitForFocus(function() { + test(synthesizeMouse, "click", "mousedown", "mousemove", "mouseup"); + test(synthesizeTouch, "tap", "touchstart", "touchmove", "touchend"); + SimpleTest.finish(); +}); + +const MIDDLE_OF_RANGE = "50"; +const MINIMUM_OF_RANGE = "0"; +const MAXIMUM_OF_RANGE = "100"; +const QUARTER_OF_RANGE = "25"; +const THREE_QUARTERS_OF_RANGE = "75"; + +function flush() { + // Flush style, specifically to flush the 'direction' property so that the + // browser uses the new value for thumb positioning. + document.body.clientWidth; +} + +function test(synthesizeFunc, clickOrTap, startName, moveName, endName) { + var elem = document.getElementById("range"); + elem.focus(); + flush(); + + var width = parseFloat(window.getComputedStyle(elem).width); + var height = parseFloat(window.getComputedStyle(elem).height); + var borderLeft = parseFloat(window.getComputedStyle(elem).borderLeftWidth); + var borderTop = parseFloat(window.getComputedStyle(elem).borderTopWidth); + var paddingLeft = parseFloat(window.getComputedStyle(elem).paddingLeft); + var paddingTop = parseFloat(window.getComputedStyle(elem).paddingTop); + + // Extrema for mouse/touch events: + var midY = height / 2 + borderTop + paddingTop; + var minX = borderLeft + paddingLeft; + var midX = minX + width / 2; + var maxX = minX + width; + + // Test click/tap in the middle of the range: + elem.value = QUARTER_OF_RANGE; + synthesizeFunc(elem, midX, midY, {}); + is(elem.value, MIDDLE_OF_RANGE, "Test " + clickOrTap + " in middle of range"); + + // Test mouse/touch dragging of ltr range: + elem.value = QUARTER_OF_RANGE; + synthesizeFunc(elem, midX, midY, { type: startName }); + is(elem.value, MIDDLE_OF_RANGE, "Test " + startName + " in middle of range"); + synthesizeFunc(elem, minX, midY, { type: moveName }); + is(elem.value, MINIMUM_OF_RANGE, "Test dragging of range to left of ltr range"); + + synthesizeFunc(elem, maxX, midY, { type: moveName }); + is(elem.value, MAXIMUM_OF_RANGE, "Test dragging of range to right of ltr range (" + moveName + ")"); + + synthesizeFunc(elem, maxX, midY, { type: endName }); + is(elem.value, MAXIMUM_OF_RANGE, "Test dragging of range to right of ltr range (" + endName + ")"); + + // Test mouse/touch dragging of rtl range: + elem.value = QUARTER_OF_RANGE; + elem.style.direction = "rtl"; + flush(); + synthesizeFunc(elem, midX, midY, { type: startName }); + is(elem.value, MIDDLE_OF_RANGE, "Test " + startName + " in middle of rtl range"); + synthesizeFunc(elem, minX, midY, { type: moveName }); + is(elem.value, MAXIMUM_OF_RANGE, "Test dragging of range to left of rtl range"); + + synthesizeFunc(elem, maxX, midY, { type: moveName }); + is(elem.value, MINIMUM_OF_RANGE, "Test dragging of range to right of rtl range (" + moveName + ")"); + + synthesizeFunc(elem, maxX, midY, { type: endName }); + is(elem.value, MINIMUM_OF_RANGE, "Test dragging of range to right of rtl range (" + endName + ")"); + + elem.style.direction = "ltr"; // reset direction + flush(); + + // Test mouse/touch capturing by moving pointer to a position outside the range: + elem.value = QUARTER_OF_RANGE; + synthesizeFunc(elem, midX, midY, { type: startName }); + is(elem.value, MIDDLE_OF_RANGE, "Test " + startName + " in middle of range"); + synthesizeFunc(elem, maxX+100, midY, { type: moveName }); + is(elem.value, MAXIMUM_OF_RANGE, "Test dragging of range to position outside range (" + moveName + ")"); + + synthesizeFunc(elem, maxX+100, midY, { type: endName }); + is(elem.value, MAXIMUM_OF_RANGE, "Test dragging of range to position outside range (" + endName + ")"); + + // Test mouse/touch capturing by moving pointer to a position outside a rtl range: + elem.value = QUARTER_OF_RANGE; + elem.style.direction = "rtl"; + flush(); + synthesizeFunc(elem, midX, midY, { type: startName }); + is(elem.value, MIDDLE_OF_RANGE, "Test " + startName + " in middle of rtl range"); + synthesizeFunc(elem, maxX+100, midY, { type: moveName }); + is(elem.value, MINIMUM_OF_RANGE, "Test dragging of range to position outside range (" + moveName + ")"); + + synthesizeFunc(elem, maxX+100, midY, { type: endName }); + is(elem.value, MINIMUM_OF_RANGE, "Test dragging of range to position outside range (" + endName + ")"); + + elem.style.direction = "ltr"; // reset direction + flush(); + + // Test mouse/touch events with certain modifiers are ignored: + var modifiersIgnore = ["ctrlKey", "altGrKey", "fnKey", "osKey"]; + for (var modifier of modifiersIgnore) { + elem.value = QUARTER_OF_RANGE; + var eventParams = {}; + eventParams[modifier] = true; + synthesizeFunc(elem, midX, midY, eventParams); + is(elem.value, QUARTER_OF_RANGE, "Test " + clickOrTap + " in the middle of range with " + modifier + " modifier key is ignored"); + } + + // Test mouse/touch events with certain modifiers are allowed: + var modifiersAllow = ["shiftKey", "altKey", "metaKey"]; + for (var modifier of modifiersAllow) { + elem.value = QUARTER_OF_RANGE; + var eventParams = {}; + eventParams[modifier] = true; + synthesizeFunc(elem, midX, midY, eventParams); + is(elem.value, MIDDLE_OF_RANGE, "Test " + clickOrTap + " in the middle of range with " + modifier + " modifier key is allowed"); + } + + // Test that preventDefault() works: + function preventDefault(e) { + e.preventDefault(); + } + elem.value = QUARTER_OF_RANGE; + elem.addEventListener(startName, preventDefault); + synthesizeFunc(elem, midX, midY, {}); + is(elem.value, QUARTER_OF_RANGE, "Test that preventDefault() works"); + elem.removeEventListener(startName, preventDefault); + + // Test that changing the input type in the middle of a drag cancels the drag: + elem.value = QUARTER_OF_RANGE; + synthesizeFunc(elem, midX, midY, { type: startName }); + is(elem.value, MIDDLE_OF_RANGE, "Test " + startName + " in middle of range"); + elem.type = "text"; + is(elem.value, QUARTER_OF_RANGE, "Test that changing the input type cancels a drag"); + synthesizeFunc(elem, midX, midY, { type: endName }); + is(elem.value, QUARTER_OF_RANGE, "Test that changing the input type cancels a drag (after " + endName + ")"); + elem.type = "range"; + + // Check that we do not drag when the mousedown/touchstart occurs outside the range: + elem.value = QUARTER_OF_RANGE; + synthesizeFunc(elem, maxX+100, midY, { type: startName }); + is(elem.value, QUARTER_OF_RANGE, "Test " + startName + " outside range doesn't change its value"); + synthesizeFunc(elem, midX, midY, { type: moveName }); + is(elem.value, QUARTER_OF_RANGE, "Test dragging is not occurring when " + startName + " was outside range"); + + synthesizeFunc(elem, midX, midY, { type: endName }); + is(elem.value, QUARTER_OF_RANGE, "Test dragging is not occurring when " + startName + " was outside range"); + + elem.focus(); // RESTORE FOCUS SO WE GET THE FOCUSED STYLE FOR TESTING OR ELSE minX/midX/maxX may be wrong! + + // Check what happens when a value changing key is pressed during a drag: + elem.value = QUARTER_OF_RANGE; + synthesizeFunc(elem, midX, midY, { type: startName }); + is(elem.value, MIDDLE_OF_RANGE, "Test " + startName + " in middle of range"); + synthesizeKey("KEY_Home"); + // The KEY_Home tests are disabled until I can figure out why they fail on Android -jwatt + //is(elem.value, MINIMUM_OF_RANGE, "Test KEY_Home during a drag sets the value to the minimum of the range"); + synthesizeFunc(elem, midX+100, midY, { type: moveName }); + is(elem.value, MAXIMUM_OF_RANGE, "Test " + moveName + " outside range after key press that occurred during a drag changes the value"); + synthesizeFunc(elem, midX, midY, { type: moveName }); + is(elem.value, MIDDLE_OF_RANGE, "Test " + moveName + " in middle of range"); + synthesizeKey("KEY_Home"); + //is(elem.value, MINIMUM_OF_RANGE, "Test KEY_Home during a drag sets the value to the minimum of the range (second time)"); + synthesizeFunc(elem, maxX+100, midY, { type: endName }); + is(elem.value, MAXIMUM_OF_RANGE, "Test " + endName + " outside range after key press that occurred during a drag changes the value"); + + function hideElement() { + elem.parentNode.style.display = 'none'; + elem.parentNode.offsetLeft; + } + + if (clickOrTap == "click") { + elem.addEventListener("mousedown", hideElement); + } else if (clickOrTap == "tap") { + elem.addEventListener("touchstart", hideElement); + } + synthesizeFunc(elem, midX, midY, { type: startName }); + synthesizeFunc(elem, midX, midY, { type: endName }); + elem.removeEventListener("mousedown", hideElement); + elem.removeEventListener("touchstart", hideElement); + ok(true, "Hiding the element during mousedown/touchstart shouldn't crash the process."); + elem.parentNode.style.display = "block"; + elem.parentNode.offsetLeft; +} + +</script> +</pre> +</body> +</html> |