chromium/third_party/blink/web_tests/fast/events/document-elementFromPoint.html

<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="initial-scale=1, minimum-scale=1, maximum-scale=1">
<style>
* {
    margin: 0;
    padding: 0;
}

body {
    height: 2048px;
    width: 2048px;
    cursor: crosshair; /* Debugging */
}

.box {
    width: 200px;
    height: 100px;
    border: 10px solid gray;
}

.line {
    width:150px;
    height:20px;
    background: gray;
}

.target {
    background: lightGreen !important; /* Elements we click on are green */
}

#absolute {
    position: absolute;
    left: 100px;
    top: 125px;
}

#relative {
    position: relative;
    left: 40px;
    top: -50px;
}

#fixed {
    position: fixed;
    top: 50px;
    left: 200px;
    height: 50px;
}

#filler {
    position: absolute;
    top: 0;
    width: 100%;
    height: 100%;
}

table {
    margin-top: 300px;
    margin-left: 40px;
    width: 400px;
}

th { height: 30px; }

#table-content {
    position: relative;
    border: 10px solid gray;
}

#columns {
    position: absolute;
    width: 400px;
    height: 200px;
    top: 220px;
    left: 500px;
    border: 1px solid black;
    -webkit-column-count: 3;
    column-count: 3;
    column-fill: auto;
}

.column-line {
    width: 100px;
    height: 20px;
    background: gray;
}

#transformed {
    position: absolute;
    top: 470px;
    height: 120px;
    width: 200px;
    transform: translate(100px, 50px) rotate(20deg);
}

#overflow {
    overflow: hidden; /* No scrollbars */
    position: absolute;
    width: 300px;
    height: 200px;
    top: 450px;
    left: 470px;
    border: 1px solid black;
    direction: rtl;
}

#overflow-contents {
    height: 500px;
    width: 120%;
}

#inside-overflow {
    height: 550px;
    width: 50%;
}

#results {
    position: absolute;
    left: 30px;
    top: 750px;
}

#mouse-position {
    position: absolute;
    left: 30px;
    top: 670px;
    color: gray;
}
</style>
</head>
<body>
    
<!--
  This test is modelled after <LayoutTests/fast/events/offsetX-offsetY.html>,
  but it is designed to not depend on inline text content to position the
  targets on which we click.
-->

<!-- Filler, to force scrolling -->
<div id="filler"></div>

<!-- Absolute, Relative, and Fixed position -->
<div id="absolute" class="box target">
    <span style="position:absolute;left:0;top:0">Absolute</span>
    <div id="relative" class="box target">Relative</div>
    <div id="fixed" class="box target">Fixed</div>
</div>

<!-- Table -->
<table id="table" border="2" cellpadding="3" cellpadding="2">
    <tr><th>x</th><th>x</th></tr>
    <tr>
        <td><div id="table-content" class="line target">Table Content</div></td>
        <td>
            <div class="line"></div><div class="line"></div>
            <div class="line"></div><div class="line"></div>
            <div class="line"></div><div class="line"></div>
        </td>
    </tr>
</table>

<!-- Columns -->
<div id="columns">
    <div class="column-line"></div><div class="column-line"></div>
    <div class="column-line"></div><div class="column-line"></div>
    <div class="column-line"></div><div class="column-line"></div>
    <div class="column-line"></div><div class="column-line"></div>
    <div class="column-line"></div><div class="column-line"></div>
    <div class="column-line"></div><div class="column-line"></div>
    <div id="in-columns" class="column-line target">In Columns</div>
    <div class="column-line"></div><div class="column-line"></div>
    <div class="column-line"></div><div class="column-line"></div>
    <div class="column-line"></div><div class="column-line"></div>
    <div class="column-line"></div><div class="column-line"></div>
    <div class="column-line"></div><div class="column-line"></div>
    <div class="column-line"></div><div class="column-line"></div>
    <div class="column-line"></div><div class="column-line"></div>
</div>

<!-- Transformed -->
<div id="transformed" class="box target">Transformed</div>

<!-- Overflowed Content -->
<div id="overflow">
    <div id="overflow-contents">
        <div class="line"></div><div class="line"></div><div class="line"></div>
        <div class="line"></div><div class="line"></div><div class="line"></div>
        <div class="line"></div><div class="line"></div><div class="line"></div>
        <div id="inside-overflow" class="target">In RTL overflow</div>
        <div class="line"></div><div class="line"></div><div class="line"></div>
    </div>
</div>

<!-- Debugging -->
<div id="results"></div>
<div id="mouse-position"></div>

<script>
// Debug mode.
if (!window.testRunner) {
    document.body.onmousemove = function(e) {
        var resultBox = document.getElementById('mouse-position');
        var offsets = 'element id: ' + e.target.id + '<br> clientX: ' + e.clientX + ' clientY: ' + e.clientY + '<br>';
        offsets += 'offsetX: ' + e.offsetX + ' offsetY: ' + e.offsetY;
        resultBox.innerHTML = offsets;
    }
}

function log(s) {
    var resultsDiv = document.getElementById('results');
    resultsDiv.innerHTML += s + '<br>';
}

function dispatchEvent(clientX, clientY, expectedElementID, expectedOffsetX, expectedOffsetY) {
    var e = document.createEvent("MouseEvent");
    e.initMouseEvent("click", true, true, window, 1, 1, 1, clientX, clientY, false, false, false, false, 0, document);
    e.expectedElementID = expectedElementID;
    e.expectedOffsetX = expectedOffsetX;
    e.expectedOffsetY = expectedOffsetY;
    var target = document.elementFromPoint(e.clientX, e.clientY);
    target.dispatchEvent(e);   
}

function clicked(event) {
    var element = event.target;
    var result;
    if (element.id === event.expectedElementID && event.offsetX === event.expectedOffsetX && event.offsetY === event.expectedOffsetY) {
        result = 'PASS:';
        result += ' event at (' + event.clientX + ', ' + event.clientY + ')';
        result += ' hit ' + element.id;
        result += ' at offset (' + event.offsetX + ', ' + event.offsetY + ')';
    } else {
        result = 'FAIL:';
        result += ' event at (' + event.clientX + ', ' + event.clientY + ')';
        result += ' expected to hit ' + event.expectedElementID;
        result += ' at (' + event.expectedOffsetX + ', ' + event.expectedOffsetY + ')';
        result += ' but hit ' + element.id + ' at (' + event.offsetX + ', ' + event.offsetY + ')';
    }
    log(result);
}

if (window.testRunner) {
    testRunner.dumpAsText();
    testRunner.waitUntilDone();
}

// Start the test.
document.body.addEventListener('click', clicked, false);
window.addEventListener('load', function() {
    setTimeout(function() {
        // Scroll body and inner overflow box.
        window.scrollTo(20, 100);
        var overflowContent = document.getElementById('overflow');
        overflowContent.scrollLeft = 0;
        overflowContent.scrollTop = 60;
        setTimeout(function() {
            // Dispatch events.
            dispatchEvent(109, 57, 'absolute', 19, 22);
            dispatchEvent(161, 13, 'relative', 21, 18);
            dispatchEvent(40, 297, 'table-content', 5, 8);
            dispatchEvent(122, 407, 'transformed', 8, 5);
            dispatchEvent(573, 480, 'inside-overflow', 2, 9);
            dispatchEvent(707, 174, 'in-columns', 87, 13);
            dispatchEvent(241, 67, 'fixed', 31, 7);
            dispatchEvent(244, 102, 'fixed', 34, 42);
            dispatchEvent(388, 88, 'fixed', 178, 28);

            // End asynchronous test.
            if (window.testRunner)
                testRunner.notifyDone();            
        }, 0);
    }, 0);
}, false);
</script>
</body>
</html>