chromium/third_party/blink/web_tests/fast/events/menu-key-context-menu-document-pinch-zoom.html

<!DOCTYPE html>

<script src="../../resources/js-test.js"></script>
<script src="../dom/resources/event-sender-util.js"></script>

<script>
description('This test checks if contextmenu event target is correct when handled at the document level and in the' +
            ' presence of pinch-zoom. To test manually, first pinch-zoom into the page, scroll away from the origin' +
            ' and then then press the menu key. There are three cases to check: nothing focused (the context menu is' +
            ' expected to appear in the top left of the viewport), click on the orange box to focus it then use the' +
            ' menu key, and select some text in the box and use the menu key. Note: on Mac there is no menu key.');

// Visual Viewport will be at the bottom right quadrant of the page.
var visualViewportContentX = 400;
var visualViewportContentY = 300;
var scale = 2;

// Should match the static const in EventHandler::ShowNonLocatedContextMenu
var kContextMenuMargin = 1;

var expectedX;
var expectedY;
var expectedScreenX;
var expectedScreenY;
var event;

var anchor;
var textbox;

function handleContextMenuNoFocus(e) {
    event = e;
    expectedX = kContextMenuMargin + visualViewportContentX;
    expectedY = kContextMenuMargin + visualViewportContentY;
    expectedScreenX = kContextMenuMargin * scale;
    expectedScreenY = kContextMenuMargin * scale;
    shouldBe('event.clientX', 'expectedX');
    shouldBe('event.clientY', 'expectedY');
    shouldBe('event.screenX', 'expectedScreenX');
    shouldBe('event.screenY', 'expectedScreenY');
    e.preventDefault();
}

function handleContextMenuFocus(e) {
    event = e;
    expectedX = anchor.offsetLeft + anchor.offsetWidth/2;
    expectedY = anchor.offsetTop + anchor.offsetHeight/2;
    expectedScreenX = (expectedX - visualViewportContentX) * scale;
    expectedScreenY = (expectedY - visualViewportContentY) * scale;
    shouldBe('event.clientX', 'expectedX');
    shouldBe('event.clientY', 'expectedY');
    shouldBe('event.screenX', 'expectedScreenX');
    shouldBe('event.screenY', 'expectedScreenY');
    e.preventDefault();
}

function handleContextMenuEditable(e) {
    event = e;

    var rangeRect = window.getSelection().getRangeAt(0).getBoundingClientRect();
    expectedX = rangeRect.left;

    // EventHandler::ShowNonLocatedContextMenu takes the midpoint of the y values
    // so that the context menu doesn't end up in the next line on multiline
    // selections.
    expectedY = Math.floor((rangeRect.bottom + rangeRect.top) / 2);

    expectedScreenX = (expectedX - visualViewportContentX) * scale;
    expectedScreenY = (expectedY - visualViewportContentY) * scale;

    shouldBe('event.clientX', 'expectedX');
    shouldBe('event.clientY', 'expectedY');
    shouldBe('event.screenX', 'expectedScreenX');
    shouldBe('event.screenY', 'expectedScreenY');
    e.preventDefault();
}

var runTest = function() {
    internals.setPageScaleFactor(scale);
    internals.setVisualViewportOffset(visualViewportContentX, visualViewportContentY);

    anchor = document.getElementById("anchor");

    // With nothing focused, the context menu should appear in the top left
    // corner of the viewport.
    document.addEventListener('contextmenu', handleContextMenuNoFocus, true);
    eventSender.keyDown("ContextMenu");
    eventSender.keyDown("Escape");
    document.removeEventListener('contextmenu', handleContextMenuNoFocus, true);

    // Focus the anchor, make sure the client coordinates and screen coordinates
    // take the viewport's position and scale into account.
    anchor.focus();
    document.addEventListener('contextmenu', handleContextMenuFocus, true);
    eventSender.keyDown("ContextMenu");
    eventSender.keyDown("Escape");
    document.removeEventListener('contextmenu', handleContextMenuFocus, true);

    // Place selection and make sure it still works.
    window.getSelection().selectAllChildren(anchor);
    document.addEventListener('contextmenu', handleContextMenuEditable, true);
    eventSender.keyDown("ContextMenu");
    eventSender.keyDown("Escape");
    document.removeEventListener('contextmenu', handleContextMenuEditable, true);

    testRunner.notifyDone();
}

if (!window.eventSender || !window.testRunner || !window.internals) {
    testFailed('This test needs to run in a test environment.');
    document.addEventListener('contextmenu', handleContextMenuEditable, true);
} else {
    testRunner.waitUntilDone();
    window.addEventListener('load', runTest);
}
</script>

<style>
#anchor {
    background-color: orange;
    position: absolute;
    top: 380px;
    left: 530px;
    height: 100px;
    width: 100px;
}
</style>
<div id="anchor" tabindex="0">Target</div>
<div id="console"></div>