<!doctype html>
<html>
<head>
<script src="../../resources/js-test-pre.js"></script>
<style>
input {
    background-color: rgb(1, 2, 3);
    color: rgb(4, 5, 6);
}
input:in-range {
    background-color: rgb(7, 8, 9);
}
input:out-of-range {
    color: rgb(10, 11, 12);
}
</style>
</head>
<body>
    <div id="with-renderer">
        <input type="number" id="number-with-renderer"></input>
        <input type="range" id="range-with-renderer"></input>
    </div>
    <div style="display:none;">
        <input type="number" id="number-without-renderer"></input>
        <input type="range" id="range-without-renderer"></input>
    </div>
</body>
<script>
description('Test the style update with the :in-range and :out-of-range pseudo classes.');

function elementsWithStyle(propertyName, propertyValue) {
    let filteredElements = [];
    let allInput = document.querySelectorAll("input");
    for (let inputElement of allInput) {
        let computedStyle = getComputedStyle(inputElement);
        if (computedStyle[propertyName] === propertyValue)
            filteredElements.push(inputElement.id);
    }
    return filteredElements;
}
function inRange() {
    return elementsWithStyle("background-color", "rgb(7, 8, 9)");
}
function outOfRange() {
    return elementsWithStyle("color", "rgb(10, 11, 12)");
}

function setAttribute(typeString, attributeName, attributeValue) {
    let inputElements = document.querySelectorAll("input[type=\"" + typeString + "\"]");
    for (let inputElement of inputElements) {
        inputElement.setAttribute(attributeName, attributeValue);
    }
}

function removeAttribute(typeString, attributeName) {
    let inputElements = document.querySelectorAll("input[type=\"" + typeString + "\"]");
    for (let inputElement of inputElements) {
        inputElement.removeAttribute(attributeName);
    }
}

debug("Initial state.");
shouldBe("inRange()", "['range-with-renderer', 'range-without-renderer']");
shouldBe("outOfRange()", "[]");

// Define a minimum.
debug("Set a valid minimum on number.");
setAttribute("number", "min", "42");
shouldBe("inRange()", "['number-with-renderer', 'range-with-renderer', 'number-without-renderer', 'range-without-renderer']");
shouldBe("outOfRange()", "[]");

debug("Set a valid minimum on range.");
setAttribute("range", "min", "42");
shouldBe("inRange()", "['number-with-renderer', 'range-with-renderer', 'number-without-renderer', 'range-without-renderer']");
shouldBe("outOfRange()", "[]");

debug("Set a value above minimum on number.");
setAttribute("number", "value", "43");
shouldBe("inRange()", "['number-with-renderer', 'range-with-renderer', 'number-without-renderer', 'range-without-renderer']");
shouldBe("outOfRange()", "[]");

debug("Set a value above minimum on range.");
setAttribute("range", "value", "43");
shouldBe("inRange()", "['number-with-renderer', 'range-with-renderer', 'number-without-renderer', 'range-without-renderer']");
shouldBe("outOfRange()", "[]");

debug("Set a value under minimum on number.");
setAttribute("number", "value", "41");
shouldBe("inRange()", "['range-with-renderer', 'range-without-renderer']");
shouldBe("outOfRange()", "['number-with-renderer', 'number-without-renderer']");

debug("Set a value under minimum on range.");
setAttribute("range", "value", "41");
shouldBe("inRange()", "['range-with-renderer', 'range-without-renderer']");
shouldBe("outOfRange()", "['number-with-renderer', 'number-without-renderer']");

debug("Set an invalid minimum on number.");
setAttribute("number", "min", "WebKit!");
shouldBe("inRange()", "['range-with-renderer', 'range-without-renderer']");
shouldBe("outOfRange()", "[]");

debug("Set an invalid minimum on range.");
setAttribute("range", "min", "WebKit!");
shouldBe("inRange()", "['range-with-renderer', 'range-without-renderer']");
shouldBe("outOfRange()", "[]");

// Define a maximum.
debug("Set a valid maximum on number.");
setAttribute("number", "max", "101");
shouldBe("inRange()", "['number-with-renderer', 'range-with-renderer', 'number-without-renderer', 'range-without-renderer']");
shouldBe("outOfRange()", "[]");

debug("Set a valid maximum on range.");
setAttribute("range", "max", "101");
shouldBe("inRange()", "['number-with-renderer', 'range-with-renderer', 'number-without-renderer', 'range-without-renderer']");
shouldBe("outOfRange()", "[]");

debug("Set a value under maximum on number.");
setAttribute("number", "value", "0");
shouldBe("inRange()", "['number-with-renderer', 'range-with-renderer', 'number-without-renderer', 'range-without-renderer']");
shouldBe("outOfRange()", "[]");

debug("Set a value under maximum on range.");
setAttribute("range", "value", "0");
shouldBe("inRange()", "['number-with-renderer', 'range-with-renderer', 'number-without-renderer', 'range-without-renderer']");
shouldBe("outOfRange()", "[]");

debug("Set a value over maximum on number.");
setAttribute("number", "value", "103");
shouldBe("inRange()", "['range-with-renderer', 'range-without-renderer']");
shouldBe("outOfRange()", "['number-with-renderer', 'number-without-renderer']");

debug("Set a value over maximum on range.");
setAttribute("range", "value", "103");
shouldBe("inRange()", "['range-with-renderer', 'range-without-renderer']");
shouldBe("outOfRange()", "['number-with-renderer', 'number-without-renderer']");

debug("Set an invalid maximum on number.");
setAttribute("number", "max", "WebKit!");
shouldBe("inRange()", "['range-with-renderer', 'range-without-renderer']");
shouldBe("outOfRange()", "[]");

debug("Set an invalid maximum on range.");
setAttribute("range", "max", "WebKit!");
shouldBe("inRange()", "['range-with-renderer', 'range-without-renderer']");
shouldBe("outOfRange()", "[]");

// Set a full state in range.
debug("Set values, min and max in range on both");
setAttribute("range", "value", "42");
setAttribute("range", "min", "1");
setAttribute("range", "max", "103");
setAttribute("number", "value", "-42");
setAttribute("number", "min", "-100");
setAttribute("number", "max", "-3");
shouldBe("inRange()", "['number-with-renderer', 'range-with-renderer', 'number-without-renderer', 'range-without-renderer']");
shouldBe("outOfRange()", "[]");

// A disabled input should not match either selectors.
debug("Disable range");
setAttribute("range", "disabled", "");
shouldBe("inRange()", "['number-with-renderer', 'number-without-renderer']");
shouldBe("outOfRange()", "[]");

debug("Disable number");
setAttribute("number", "disabled", "");
shouldBe("inRange()", "[]");
shouldBe("outOfRange()", "[]");

debug("Set number out of range");
setAttribute("number", "value", "55");
shouldBe("inRange()", "[]");
shouldBe("outOfRange()", "[]");

debug("Set range out of range");
setAttribute("range", "value", "1024");
shouldBe("inRange()", "[]");
shouldBe("outOfRange()", "[]");

debug("Re-enable range");
removeAttribute("range", "disabled");
shouldBe("inRange()", "['range-with-renderer', 'range-without-renderer']");
shouldBe("outOfRange()", "[]");

debug("Re-enable number");
removeAttribute("number", "disabled");
shouldBe("inRange()", "['range-with-renderer', 'range-without-renderer']");
shouldBe("outOfRange()", "['number-with-renderer', 'number-without-renderer']");

// A readonly input should not match either selectors.
debug("Make number read-only");
setAttribute("number", "readonly", "");
shouldBe("inRange()", "['range-with-renderer', 'range-without-renderer']");
shouldBe("outOfRange()", "[]");

debug("Make range read-only");
setAttribute("range", "readonly", "");
shouldBe("inRange()", "[]");
shouldBe("outOfRange()", "[]");

debug("Set range in range");
setAttribute("range", "value", "74");
shouldBe("inRange()", "[]");
shouldBe("outOfRange()", "[]");

debug("Set number in range");
setAttribute("number", "value", "-69");
shouldBe("inRange()", "[]");
shouldBe("outOfRange()", "[]");

debug("Remove read-only from number");
removeAttribute("number", "readonly");
shouldBe("inRange()", "['number-with-renderer', 'number-without-renderer']");
shouldBe("outOfRange()", "[]");

debug("Remove read-only from range");
removeAttribute("range", "readonly");
shouldBe("inRange()", "['number-with-renderer', 'range-with-renderer', 'number-without-renderer', 'range-without-renderer']");
shouldBe("outOfRange()", "[]");

debug("Remove min from number");
removeAttribute("number", "min");
shouldBe("inRange()", "['number-with-renderer', 'range-with-renderer', 'number-without-renderer', 'range-without-renderer']");
shouldBe("outOfRange()", "[]");

debug("Remove max from number");
removeAttribute("number", "max");
shouldBe("inRange()", "['range-with-renderer', 'range-without-renderer']");
shouldBe("outOfRange()", "[]");

debug("Remove min from range");
removeAttribute("range", "min");
shouldBe("inRange()", "['range-with-renderer', 'range-without-renderer']");
shouldBe("outOfRange()", "[]");

debug("Remove max from range");
removeAttribute("range", "min");
shouldBe("inRange()", "['range-with-renderer', 'range-without-renderer']");
shouldBe("outOfRange()", "[]");

// Hides the elements to make the result page pretty.
document.getElementById("with-renderer").style.display = "none";
</script>
<script src="../../resources/js-test-post.js"></script>
</html>
