chromium/third_party/blink/web_tests/editing/selection/hit-test-on-text-with-line-height.html

<!DOCTYPE html>
<script src="../../resources/ahem.js"></script>
<script src="../../resources/testharness.js"></script>
<script src="../../resources/testharnessreport.js"></script>
<script src="../assert_selection.js"></script>
<script>
// This test ensures Blink can place caret after the line even when the line-
// height is smaller than a line.
//
// To manually test, click inside the editable outside the red box.
// The caret should be placed at the end of "sample".
//
// Also test that when you click in the red box above or below the editable,
// caret is placed at where you clicked.
const kSample = 'abcd';
const kFontSize = 30;
const kLineHeight = 10;
const kPadding = 5;
const kSampleWidth = kFontSize * kSample.length;
const kWidth = 200;
const kStyle = [
    'border: solid 1px black;',
    `font: ${kFontSize}px/${kLineHeight}px Ahem;`,
    'padding: 5px;',
    `width: ${kWidth}px;`,
].join('');
const kStyle2 = [
    'border: solid 1px red;',
].join('');

function testIt(platform, title, id, x, y, expected) {
    selection_test(
        [
            `<div contenteditable id="editable" style="${kStyle}">`,
                `<b id="sample" style="${kStyle2}">${kSample}</b>`,
            '</div>',
        ],
        selection => {
            const sample = selection.document.getElementById('sample');
            const target = selection.document.getElementById(id);
            if (!window.eventSender)
                throw 'This test requires eventSender.';
            const offsetX = x === 'after'
                ? sample.offsetWidth
                : Math.min(x, sample.offsetWidth);
            const offsetY = {
                'above': 15,
                'below': sample.offsetHeight - 15,
                'top': 10,
                'middle': target.offsetHeight / 2,
                'bottom': target.offsetHeight - 5,
            }[y];
            eventSender.leapForward(9999); // reset mouse click state
            eventSender.mouseMoveTo(selection.computeLeft(target) + offsetX,
                                    selection.computeTop(target) + offsetY);
            eventSender.mouseDown();
            eventSender.leapForward(500);
            eventSender.mouseUp();
        },
        [
            `<div contenteditable id="editable" style="${kStyle}">`,
                `<b id="sample" style="${kStyle2}">${expected}</b>`,
            '</div>',
        ],
        `${platform}: ${title}`);
}

for (const platform of ['android', 'mac', 'unix', 'win']) {
    if (window.internals)
        internals.settings.setEditingBehavior(platform);
    testIt(platform, 'Click after sample (top)', 'editable',
           'after', 'top', 'abcd|');
    testIt(platform, 'Click after sample (middle)', 'editable',
            'after', 'middle', 'abcd|');
    testIt(platform, 'Click after sample (bottom)', 'editable',
            'after', 'bottom', 'abcd|');

    for (let i = 0; i <= kSample.length; ++i) {
        const x = i * kFontSize;
        const expected = `${kSample.substr(0, i)}|${kSample.substr(i)}`;
        testIt(platform, `Click above editable at ${expected}`, 'sample',
               x + 1, 'above', expected);
        testIt(platform, `Click below editable at ${expected}`, 'sample',
               x + 1, 'below', expected);
    }
}
</script>