chromium/third_party/blink/web_tests/editing/selection/caret-at-bidi-boundary.html

<!DOCTYPE html>
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8">
<script src="../../resources/js-test.js"></script>
<style type="text/css">
#tests { font-size: 2.5em; padding: 0px; margin: 0px; }
dt { width: 15ex; padding: 0px 10px; margin: 0px; }
dd { font-size: 0.6em; margin: 0px; padding: 0px 10px; }
.target { background-color: #bbeeff; }
.bidi-caret { display: none }
</style>
</head>
<body>
<p>This test ensures WebKit lets user place caret around bidirectional text properly.</p>
<div>Current offset: <span id="log"></span></div>
<dl id="tests">
<dt contenteditable>abcאבג</dt>
<dd>0 1 2 3 5 4 6</dd>
<div class="bidi-caret">0 1 2 3 6 5 4 3</div>

<dt contenteditable>נת12</dt>
<dd>2 3 4 1 4 (There is a bug. Clicking on the left of 12 should result in offset 0.)</dd>
<div class="bidi-caret">2 3 4 2 1 0</div>

<dt contenteditable>לש<b>נ</b>ת</dt>
<dd>0 3 2 1 4</dd>
<div class="bidi-caret">4 3 2 1 0</div>

<dt contenteditable>aקל12יםd</dt>
<dd>0 1 6 3 4 5 2 7 8</dd>
<div class="bidi-caret">0 1 7 6 5 3 4 5 3 2 1 7 8</div>

<dt><span dir="rtl">12<b>קל43</b></span>ab</dt>
<dd>4 5 6 3 0 1 2 7 8</dd>
<div class="bidi-caret">4 5 6 4 3 2 0 1 2 6 7 8</div>

<dt dir="rtl"><span dir="ltr">abcלשנ</span></dt>
<dd>6 1 2 6 5 4 3</dd>
<div class="bidi-caret">0 1 2 3 6 5 4 3</div>

</dl>
<div id="console"></div>
<pre><script>

// This function converts (node, offset) pair to a global offset (like TextIterator index).
function globalOffsetFromNodeOffsetPair(node, offsetInNode) {
    var tests = document.getElementById('tests');
    var testContainer = node;
    while (testContainer && testContainer.parentNode != tests)
        testContainer = testContainer.parentNode;
    if (!testContainer)
        return 'a node outside of tests';

    return testContainer.textContent.indexOf(node.textContent) + offsetInNode;
}

function runTest(target, expectations) {
    var y = target.offsetTop + target.offsetHeight / 2;

    var previousOffset = -1;
    var j = 0;
    for (var x = 5; x <= target.offsetWidth - 5; x += 10) {
        // Reset the click count
        eventSender.mouseMoveTo(1, 1);
        eventSender.mouseDown();
        eventSender.mouseUp();

        eventSender.mouseMoveTo(target.offsetLeft + x, y);
        eventSender.mouseDown();
        eventSender.mouseUp();

        var currentOffset = globalOffsetFromNodeOffsetPair(getSelection().baseNode, getSelection().baseOffset);
        if (!getSelection().isCollapsed)
            testFailed('selection was not collapsed');
        else if (previousOffset == currentOffset)
            continue;
        else {
            previousOffset = currentOffset;

            if (expectations[j] != currentOffset)
                testFailed('caret was at ' + currentOffset + ' but expected to be at ' + expectations[j]);
            else {
                testPassed('caret is at ' + currentOffset);
                j++;
                if (j >= expectations.length)
                    return;
            }
        }
    }

    if (j < expectations.length)
        testFailed('caret never reached offset' + expectations[j]);
}

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

    var tests = document.getElementById('tests').getElementsByTagName('dt');
    var testExpectations = document.getElementById('tests').getElementsByTagName('dd');
    if (internals.runtimeFlags.bidiCaretAffinityEnabled) {
        // When bidi caret affinity is enabled, carets are shown at different visual locations.
        // Use the changed test expectations in this case.
        var expectations = document.querySelectorAll('.bidi-caret');
        for (var i = 0; i < testExpectations.length; i++) {
            testExpectations[i].firstChild.remove();
            testExpectations[i].appendChild(expectations[i].firstChild);
        }
    }
    for (var i = 0; i < tests.length; i++) {
        debug('Test "' + tests[i].textContent + '":');
        runTest(tests[i], testExpectations[i].textContent.replace(/\s*\(.+\)\s*/, '').split(/\s+/).map(function (x) {return parseInt(x);}));
        debug('');
    }
} else {
    debug('This test requires eventSender');
    document.onselectionchange = function () {
        var selection = window.getSelection();
        document.getElementById('log').textContent = globalOffsetFromNodeOffsetPair(selection.baseNode, selection.baseOffset) + ', ' +
            globalOffsetFromNodeOffsetPair(selection.extentNode, selection.extentOffset);
    }
}


</script>
</body>
</html>