chromium/third_party/blink/web_tests/fast/events/touch/gesture/focus-selectionchange-on-tap.html

<!DOCTYPE html>
<style>
#target {
  position: absolute;
  top: 10px;
  right: 10px;
}
#target:focus {
  background-color: rgb(255, 0, 0);
}
</style>
<input type=text id=target>
<script src="../../../../resources/js-test.js"></script>
<script>
description("Verifies that a GestureTap triggers focus and selectionchange if and only if mousedown isn't prevented.");

function logEvent(e, opt_extra) {
    var msg = 'Received ' + e.type + ' on ' + (e.target.id || e.target.nodeName);
    if (opt_extra)
        msg += ' ' + opt_extra;
    debug(msg);
}

var target = document.getElementById('target');
var eventsToLog = ['mousemove', 'mousedown', 'mouseover', 'mouseup', 'mouseout', 'click'];
for (var i = 0; i < eventsToLog.length; i++) {
    target.addEventListener(eventsToLog[i], logEvent);
}
document.addEventListener('selectionchange', function(e) {
    var selection = getSelection();
    var selectionNode = selection.anchorNode;
    var anchor = 'none';
    if (selectionNode)
        anchor = (selectionNode.id || selectionNode.nodeName) + '[' + selection.anchorOffset + ']';
    logEvent(e, 'anchor=' + anchor);
});

var tapHandled;
function doTap(targetNode, expectHandled) {
    var rect = targetNode.getBoundingClientRect();
    var targetX = rect.left + 2;
    var targetY = rect.top + 2;
    
    return new Promise(function(resolve, reject) {
        if (!('eventSender' in window)) {
            reject(Error('test requires eventSender'));
            return;
        }

        debug('Sending GestureTapDown');
        eventSender.gestureTapDown(targetX, targetY, 30, 30);
        debug('Sending GestureShowPress');
        eventSender.gestureShowPress(targetX, targetY, 30, 30);
        debug('Sending GestureTap');
        tapHandled = eventSender.gestureTap(targetX, targetY, 1, 30, 30);
        shouldBe('tapHandled', expectHandled ? 'true' : 'false');

        // Run any pending tasks before resolving the promise.
        setTimeout(resolve, 0);
    });
}

function consumeEvent(e) {
    e.preventDefault();
}

function isFocused(element) {
    var style = getComputedStyle(element);
    return style.backgroundColor == 'rgb(255, 0, 0)';
}

function case1() {
    return new Promise(function(resolve, reject) {
        debug('Tap on input field but consume mousedown');
        target.addEventListener('mousedown', consumeEvent);
        doTap(target, true).then(function() {
            shouldBeFalse('isFocused(target)');
            debug('');
        }).then(resolve, reject);
    });
}

function case2() {
    return new Promise(function(resolve, reject) {
        debug('Tap on input field without consuming mousedown');
        target.removeEventListener('mousedown', consumeEvent);
        doTap(target, false).then(function() {
            shouldBeTrue('isFocused(target)');
            debug('');
        }).then(resolve, reject);
    });

}

function case3() {
    return new Promise(function(resolve, reject) {
        debug ('Tap elsewhere to clear focus');
        doTap(document.getElementById('description'), false).then(function() {
            shouldBeFalse('isFocused(target)');
            debug('');
        }).then(resolve, reject);
    });
}

jsTestIsAsync = true;
onload = function() {
    case1()
    .then(case2)
    .then(case3)
    .catch(function(err) {
      testFailed("Promise rejected: " + err.message);
    }).then(finishJSTest);
};

</script>