chromium/third_party/blink/web_tests/external/wpt/css/selectors/dir-pseudo-on-input-element.html

<!DOCTYPE html>
<meta name="author" title="Ryosuke Niwa" href="mailto:[email protected]">
<link rel="help" href="https://html.spec.whatwg.org/multipage/dom.html#the-directionality">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<body>
<script>
test(() => {
    const input = document.createElement('input');
    input.type = 'tel';
    assert_true(input.matches(':dir(ltr)'));
    assert_false(input.matches(':dir(rtl)'));

    input.setAttribute('dir', 'foo');
    assert_true(input.matches(':dir(ltr)'));
    assert_false(input.matches(':dir(rtl)'));

    input.setAttribute('dir', 'rtl');
    assert_false(input.matches(':dir(ltr)'));
    assert_true(input.matches(':dir(rtl)'));

    input.setAttribute('dir', 'RTL');
    assert_false(input.matches(':dir(ltr)'));
    assert_true(input.matches(':dir(rtl)'));

    input.setAttribute('dir', 'ltr');
    assert_true(input.matches(':dir(ltr)'));
    assert_false(input.matches(':dir(rtl)'));

    input.setAttribute('dir', 'LTR');
    assert_true(input.matches(':dir(ltr)'));
    assert_false(input.matches(':dir(rtl)'));

    input.setAttribute('dir', 'auto');
    assert_true(input.matches(':dir(ltr)'));
    assert_false(input.matches(':dir(rtl)'));

    input.value = '\u05EA';
    assert_false(input.matches(':dir(ltr)'));
    assert_true(input.matches(':dir(rtl)'));

    input.setAttribute('dir', 'AUTO');
    assert_false(input.matches(':dir(ltr)'));
    assert_true(input.matches(':dir(rtl)'));

    input.removeAttribute('dir');
    assert_true(input.matches(':dir(ltr)'));
    assert_false(input.matches(':dir(rtl)'));
}, 'input element whose type attribute is in the telephone state');

test(() => {
    const input = document.createElement('input');
    input.type = 'tel';

    const container = document.createElement('div');
    container.setAttribute('dir', 'rtl');
    container.appendChild(input);

    // Insert the element into the document so that we can also check for
    // 'direction' in computed style.
    document.body.appendChild(container);

    assert_true(input.matches(':dir(ltr)'));
    assert_false(input.matches(':dir(rtl)'));
    // Per https://html.spec.whatwg.org/multipage/rendering.html#bidi-rendering:
    assert_equals(getComputedStyle(input).direction, 'ltr');

    // Changing to a different type causes the special type=tel rule to no longer apply.
    input.type = 'text';
    assert_false(input.matches(':dir(ltr)'));
    assert_true(input.matches(':dir(rtl)'));
    assert_equals(getComputedStyle(input).direction, 'rtl');

    // And restoring type=tel brings back that behavior.
    input.type = 'tel';
    assert_true(input.matches(':dir(ltr)'));
    assert_false(input.matches(':dir(rtl)'));
    assert_equals(getComputedStyle(input).direction, 'ltr');

    document.body.removeChild(container);
}, 'input element whose type attribute is in the telephone state in a RTL block');

for (const type of ['password', 'text', 'search', 'url', 'email', 'submit', 'reset', 'button', 'hidden']) {
    test(() => {
        const input = document.createElement('input');
        input.type = type;
        assert_true(input.matches(':dir(ltr)'));
        assert_false(input.matches(':dir(rtl)'));

        input.setAttribute('dir', 'foo');
        assert_true(input.matches(':dir(ltr)'));
        assert_false(input.matches(':dir(rtl)'));

        input.setAttribute('dir', 'rtl');
        assert_false(input.matches(':dir(ltr)'));
        assert_true(input.matches(':dir(rtl)'));

        input.setAttribute('dir', 'RTL');
        assert_false(input.matches(':dir(ltr)'));
        assert_true(input.matches(':dir(rtl)'));

        input.setAttribute('dir', 'ltr');
        assert_true(input.matches(':dir(ltr)'));
        assert_false(input.matches(':dir(rtl)'));

        input.setAttribute('dir', 'LTR');
        assert_true(input.matches(':dir(ltr)'));
        assert_false(input.matches(':dir(rtl)'));

        input.setAttribute('dir', 'auto');
        assert_true(input.matches(':dir(ltr)'));
        assert_false(input.matches(':dir(rtl)'));

        input.value = '\u05EA';
        assert_false(input.matches(':dir(ltr)'));
        assert_true(input.matches(':dir(rtl)'));

        input.setAttribute('dir', 'AUTO');
        assert_false(input.matches(':dir(ltr)'));
        assert_true(input.matches(':dir(rtl)'))

        input.removeAttribute('dir');
        assert_true(input.matches(':dir(ltr)'));
        assert_false(input.matches(':dir(rtl)'));
    }, `input element whose type attribute is in the ${type} state`);
}

test(() => {
    const input = document.createElement('input');
    input.type = 'text';
    // bidirectional character type R
    input.value = '\u05EA';
    input.setAttribute('dir', 'auto');

    const container = document.createElement('div');
    container.appendChild(input);

    assert_false(input.matches(':dir(ltr)'));
    assert_true(input.matches(':dir(rtl)'));

    // Changing to a different type that does't use value causes the bidi rule to no longer apply.
    input.type = 'radio';
    assert_true(input.matches(':dir(ltr)'));
    assert_false(input.matches(':dir(rtl)'));

    // And restoring type=text brings back that behavior.
    input.type = 'text';
    assert_false(input.matches(':dir(ltr)'));
    assert_true(input.matches(':dir(rtl)'));
}, 'dynamic changes to type of input elements affect whether value is used for dir=auto');

for (const type of ['date', 'time', 'number', 'range', 'color', 'checkbox', 'radio', 'image']) {
    test(() => {
        const input = document.createElement('input');
        input.type = type;
        assert_true(input.matches(':dir(ltr)'));
        assert_false(input.matches(':dir(rtl)'));

        input.setAttribute('dir', 'foo');
        assert_true(input.matches(':dir(ltr)'));
        assert_false(input.matches(':dir(rtl)'));

        input.setAttribute('dir', 'rtl');
        assert_false(input.matches(':dir(ltr)'));
        assert_true(input.matches(':dir(rtl)'));

        input.setAttribute('dir', 'RTL');
        assert_false(input.matches(':dir(ltr)'));
        assert_true(input.matches(':dir(rtl)'));

        input.setAttribute('dir', 'ltr');
        assert_true(input.matches(':dir(ltr)'));
        assert_false(input.matches(':dir(rtl)'));

        input.setAttribute('dir', 'LTR');
        assert_true(input.matches(':dir(ltr)'));
        assert_false(input.matches(':dir(rtl)'));

        input.setAttribute('dir', 'auto');
        assert_true(input.matches(':dir(ltr)'));
        assert_false(input.matches(':dir(rtl)'));

        input.value = '\u05EA';
        assert_true(input.matches(':dir(ltr)'));
        assert_false(input.matches(':dir(rtl)'));

        input.setAttribute('dir', 'AUTO');
        assert_true(input.matches(':dir(ltr)'));
        assert_false(input.matches(':dir(rtl)'))

        input.removeAttribute('dir');
        assert_true(input.matches(':dir(ltr)'));
        assert_false(input.matches(':dir(rtl)'));

        let rtlParent = document.createElement("div");
        rtlParent.dir = "rtl";
        input.dir = "auto";
        rtlParent.appendChild(input);
        document.body.appendChild(rtlParent); // Just for good measure.
        assert_true(input.matches(':dir(ltr)'));
        assert_false(input.matches(':dir(rtl)'));
        rtlParent.remove();
    }, `input element whose type attribute is in the ${type} state`);
}

</script>
</html>