<!doctype html>
<html>
<head>
<script src="../../http/tests/inspector/resources/inspector-test.js"></script>
<script>
function test()
{
    const color = undefined;
    const outlineColor = undefined;
    const useViewportCoordinates = false;
    const usePageCoordinates = true;

    function getHighlightRects(callback) {
        InspectorTest.evaluateInPage("JSON.stringify(Array.from(window.internals.inspectorHighlightRects()))", (error, value, wasThrown) => {
            InspectorTest.assert(!error, "Unexpected error dumping highlight: " + error);
            InspectorTest.assert(!wasThrown, "Unexpected exception when dumping highlight.");
            callback(JSON.parse(value));
        });
    }

    function dumpHighlightRects(callback) {
        getHighlightRects((highlightRects) => {
            InspectorTest.expectThat(highlightRects.length === 1, "Should be one highlight rect.");
            InspectorTest.log("Highlight Rect: " + JSON.stringify(highlightRects[0]));
            callback();
        });
    }

    let suite = InspectorTest.createAsyncSuite("DOM.highlightRect");

    suite.addTestCase({
        name: "CheckEmptyHighlight",
        description: "Should not be a highlight yet.",
        test(resolve, reject) {
            getHighlightRects((highlightRects) => {
                InspectorTest.expectThat(highlightRects.length === 0, "Should not be a highlight yet.");
                resolve();
            });
        }
    });

    suite.addTestCase({
        name: "HighlightSmallRectViewportCoordinates",
        description: "Should create a highlight using viewport coordinates.",
        test(resolve, reject) {
            let rect = new WI.Rect(0, 0, 100, 200);
            DOMAgent.highlightRect(rect.origin.x, rect.origin.y, rect.size.width, rect.size.height, color, outlineColor, useViewportCoordinates, (error) => {
                dumpHighlightRects(resolve);
            });
        }
    });

    suite.addTestCase({
        name: "HighlightSmallRectPageCoordinates",
        description: "Should create a highlight using page coordinates.",
        test(resolve, reject) {
            let rect = new WI.Rect(0, 0, 100, 200);
            DOMAgent.highlightRect(rect.origin.x, rect.origin.y, rect.size.width, rect.size.height, color, outlineColor, usePageCoordinates, (error) => {
                dumpHighlightRects(resolve);
            });
        }
    });

    suite.addTestCase({
        name: "HighlightSmallRectUnspecifiedCoordinatesUsesViewportCoordinates",
        description: "Should create a highlight using viewport coordinates if unspecified.",
        test(resolve, reject) {
            let rect = new WI.Rect(0, 0, 100, 200);
            DOMAgent.highlightRect(rect.origin.x, rect.origin.y, rect.size.width, rect.size.height, color, outlineColor, (error) => {
                dumpHighlightRects(resolve);
            });
        }
    });

    suite.addTestCase({
        name: "HighlightLargeRectViewportCoordinates",
        description: "Should create a large highlight using viewport coordinates.",
        test(resolve, reject) {
            let rect = new WI.Rect(0, 0, 100000, 200000);
            DOMAgent.highlightRect(rect.origin.x, rect.origin.y, rect.size.width, rect.size.height, color, outlineColor, useViewportCoordinates, (error) => {
                dumpHighlightRects(resolve);
            });
        }
    });

    suite.addTestCase({
        name: "HighlightLargeRectPageCoordinates",
        description: "Should create a large highlight using page coordinates.",
        test(resolve, reject) {
            let rect = new WI.Rect(0, 0, 100000, 200000);
            DOMAgent.highlightRect(rect.origin.x, rect.origin.y, rect.size.width, rect.size.height, color, outlineColor, usePageCoordinates, (error) => {
                dumpHighlightRects(resolve);
            });
        }
    });

    suite.addTestCase({
        name: "HighlightEmptyRect",
        description: "Should create an empty highlight.",
        test(resolve, reject) {
            let rect = new WI.Rect(0, 0, 0, 0);
            DOMAgent.highlightRect(rect.origin.x, rect.origin.y, rect.size.width, rect.size.height, color, outlineColor, false, (error) => {
                dumpHighlightRects(resolve);
            });
        }
    });

    InspectorTest.evaluateInPage("window.scrollTo(10, 10)", () => {
        suite.runTestCasesAndFinish();
    });
}
</script>
</head>
<body onload="runTest()">
    <p>Tests for the DOM.highlightRect command.</p>
    <!-- Ensure the page is scrollable so we can test highlight rects relative to a scroll page -->
    <div style="height:2000px; width: 2000px; background:blue"></div>
</body>
</html>
