chromium/third_party/blink/web_tests/accessibility/selection-affinity.html

<!DOCTYPE html>
<script src="../resources/testharness.js"></script>
<script src="../resources/testharnessreport.js"></script>

<div id="main" role="main">

    <p style="width: 3em; border: 1px solid #000;">
        a-b-c-d-e-f-g-h-i-j-k-l-m-n-o-p-q-r-s-t-u-v-w-x-y-z
    </p>

</div>
<div id="console"></div>

<script>
    test(function()
    {
        // Create a range selecting more and more characters of text until
        // the bounding rect has a nonzero width, indicating we got the first
        // printing character.
        var text = document.querySelector('p').firstChild;
        var range = document.createRange();
        range.setStart(text, 0);
        var i = 0;
        var bounds;
        do {
            range.setEnd(text, i);
            bounds = range.getBoundingClientRect();
            i++;
        } while (bounds.width == 0);

        // Keep extending the range until the height increases, indicating we
        // got more than one line of text.
        var startCharIndex = i - 2;
        var oneLineHeight = bounds.height;
        do {
            range.setEnd(text, i);
            bounds = range.getBoundingClientRect();
            i++;
        } while (bounds.height == oneLineHeight);
        var endCharIndex = i - 2;

        // Now we can create a range for  exactly the first line of text.
        range.setStart(text, startCharIndex);
        range.setEnd(text, endCharIndex);
        var firstLineBounds = range.getBoundingClientRect();

        // Also create a range for the second character of the second line of text.
        range.setStart(text, endCharIndex + 1);
        range.setEnd(text, endCharIndex + 2);
        var secondLineBounds = range.getBoundingClientRect();

        // Click to place the cursor at the end of the first line.
        eventSender.mouseMoveTo(firstLineBounds.right, firstLineBounds.top + 5);
        eventSender.mouseDown();
        eventSender.mouseUp();

        // Ensure the selection is at the right place.
        var sel = window.getSelection();
        assert_equals(sel.anchorNode, text);
        assert_equals(sel.anchorOffset, endCharIndex);

        // Ensure the accessible selection is at the same place in the
        // accessibility tree, with UPSTREAM affinity.
        var axRoot = accessibilityController.rootElement;
        assert_equals(axRoot.selectionAnchorObject.role, "AXRole: AXStaticText");
        assert_equals(axRoot.selectionAnchorObject.name, "a-b-c-d-e-f-g-h-i-j-k-l-m-n-o-p-q-r-s-t-u-v-w-x-y-z");
        assert_equals(axRoot.selectionFocusOffset, endCharIndex - startCharIndex);
        assert_equals(axRoot.selectionAnchorOffset, endCharIndex - startCharIndex);
        assert_equals(axRoot.selectionFocusAffinity, "upstream");
        assert_equals(axRoot.selectionAnchorAffinity, "upstream");

        // Click to place the cursor at the beginning of the next line.
        eventSender.mouseMoveTo(firstLineBounds.left, secondLineBounds.top + 5);
        eventSender.mouseDown();
        eventSender.mouseUp();

        // Ensure the selection is at the right place.
        var sel = window.getSelection();
        assert_equals(sel.anchorNode, text);
        assert_equals(sel.anchorOffset, endCharIndex);

        // Ensure the accessible selection is at the same place in the
        // accessibility tree, with DOWNSTREAM affinity.
        assert_equals(axRoot.selectionAnchorObject.role, "AXRole: AXStaticText");
        assert_equals(axRoot.selectionAnchorObject.name, "a-b-c-d-e-f-g-h-i-j-k-l-m-n-o-p-q-r-s-t-u-v-w-x-y-z");
        assert_equals(axRoot.selectionAnchorOffset, endCharIndex - startCharIndex);
        assert_equals(axRoot.selectionFocusOffset, endCharIndex - startCharIndex);
        assert_equals(axRoot.selectionAnchorAffinity, "downstream");
        assert_equals(axRoot.selectionFocusAffinity, "downstream");
    }, "Test upstream and downstream affinity of text selection.");
</script>