<!doctype html>
<html>
<head>
<script src="../../http/tests/inspector/resources/inspector-test.js"></script>
<script>
function test()
{
    let suite = InspectorTest.createAsyncSuite("DOM.showGridOverlay");

    async function getGridContainerNode() {
        let doc = await WI.domManager.requestDocument();
        let nodeId = await doc.querySelector(".grid-container");
        return WI.domManager.nodeForId(nodeId);
    }

    async function getAllGridContainerNodes() {
        let doc = await WI.domManager.requestDocument();
        let nodeIds = await doc.querySelectorAll(".grid-container");
        return nodeIds.map((nodeId) => WI.domManager.nodeForId(nodeId));
    }

    async function gridOverlayCount() {
        return InspectorTest.evaluateInPage("window.internals.inspectorGridOverlayCount()");
    }

    async function checkGridOverlayCount(expected) {
        let actual = await gridOverlayCount();
        let message;
        switch (expected) {
        case 1:
            message = "Should have 1 grid displayed.";
            break;
        default:
            message = `Should have ${expected} grids displayed.`;
            break;
        }

        InspectorTest.expectEqual(actual, expected, message);
    }

    suite.addTestCase({
        name: "DOM.showGridOverlay.ShowOneGrid",
        description: "No error occurs when requesting to show a grid overlay.",
        async test() {
            await checkGridOverlayCount(0);
            let container = await getGridContainerNode();

            InspectorTest.log("Requesting to show grid overlay for first .grid-container");
            await DOMAgent.showGridOverlay(container.id, WI.Color.fromString("magenta").toProtocol());
            await checkGridOverlayCount(1);

            // No error should occur if showing grid overlay for a node that already has one.
            InspectorTest.log("Requesting to show a different grid overlay for first .grid-container");
            await DOMAgent.showGridOverlay(container.id, WI.Color.fromString("green").toProtocol());
            await checkGridOverlayCount(1);

            // No error should occur when hiding the grid overlay.
            InspectorTest.log("Requesting to hide grid overlay");
            await DOMAgent.hideGridOverlay(container.id);
            await checkGridOverlayCount(0);
        }
    });

    suite.addTestCase({
        name: "DOM.showGridOverlay.ShowTwoGrids",
        description: "No error occurs when requesting to show multiple grid overlays.",
        async test() {
            await checkGridOverlayCount(0);
            let [first, second] = await getAllGridContainerNodes();

            InspectorTest.log("Requesting to show first grid overlay");
            await DOMAgent.showGridOverlay(first.id, WI.Color.fromString("magenta").toProtocol());
            await checkGridOverlayCount(1);

            // No error should occur if showing grid overlay for a node that already has one.
            InspectorTest.log("Requesting to show second grid overlay");
            await DOMAgent.showGridOverlay(second.id, WI.Color.fromString("green").toProtocol());
            await checkGridOverlayCount(2);

            // No error should occur when hiding the grid overlay.
            InspectorTest.log("Requesting to hide first grid overlay");
            await DOMAgent.hideGridOverlay(first.id);
            await checkGridOverlayCount(1);

            // No error should occur when hiding the grid overlay.
            InspectorTest.log("Requesting to hide second grid overlay");
            await DOMAgent.hideGridOverlay(second.id);
            await checkGridOverlayCount(0);
        }
    });

    suite.addTestCase({
        name: "DOM.showGridOverlay.HideAllGrids",
        description: "No error occurs when requesting to show multiple grid overlays.",
        async test() {
            await checkGridOverlayCount(0);
            let [first, second] = await getAllGridContainerNodes();

            InspectorTest.log("Requesting to show grid overlay");
            await DOMAgent.showGridOverlay(first.id, WI.Color.fromString("magenta").toProtocol());
            await checkGridOverlayCount(1);

            // No error should occur if showing grid overlay for a node that already has one.
            InspectorTest.log("Requesting to show a different grid overlay");
            await DOMAgent.showGridOverlay(second.id, WI.Color.fromString("green").toProtocol());
            await checkGridOverlayCount(2);

            // No error should occur when hiding the grid overlay.
            InspectorTest.log("Requesting to hide all grid overlays. Hiding all grids is idempotent and should not throw an error.");
            await DOMAgent.hideGridOverlay();
            await checkGridOverlayCount(0);

            // No error should occur when hiding the grid overlay.
            InspectorTest.log("Requesting to hide all grid overlays again, expecting none to be cleared. Hiding all grids is idempotent and should not throw an error.");
            await DOMAgent.hideGridOverlay();
            await checkGridOverlayCount(0);
        }
    });

    suite.addTestCase({
        name: "DOM.showGridOverlay.HideBeforeShowShouldError",
        description: "Return an error when requesting to hide a grid overlay when none is active for the node.",
        async test() {
            let container = await getGridContainerNode();

            await checkGridOverlayCount(0);

            InspectorTest.log("Requesting to hide grid overlay for .grid-container");
            await InspectorTest.expectException(async () => {
                await DOMAgent.hideGridOverlay(container.id);
            });

            InspectorTest.log("Requesting to hide all grid overlays. Hiding all grids is idempotent and should not throw an error.");
            await DOMAgent.hideGridOverlay();
            await checkGridOverlayCount(0);
        }
    });

    suite.addTestCase({
        name: "DOM.showGridOverlay.ForNonexistentNodeShouldError",
        description: "Return an error when requesting to show a grid overlay for a nonexistent node.",
        async test() {
            await checkGridOverlayCount(0);

            InspectorTest.log("Requesting to show grid overlay for invalid nodeId -1");
            await InspectorTest.expectException(async () => {
                await DOMAgent.showGridOverlay(-1, WI.Color.fromString("magenta").toProtocol());
            });

        await checkGridOverlayCount(0);
        }
    });

    suite.runTestCasesAndFinish();
}
</script>
</head>
<body onload="runTest()">
    <style>
        body {
            margin: 100px;
        }
        .grid-container {
            display: grid;
            grid-gap: 10px;
            grid-template-columns: 100px 100px 100px;
            background-color: white;
            color: gray;
        }

        .grid-container > .box {
            background-color: gray;
            color: white;
            border-radius: 5px;
            padding: 20px;
            font-size: 150%;
        }
    </style>

    <p>Tests for the DOM.showGridOverlay command.</p>
    <div class="grid-container" style="color: #366">
        <div class="box a">A</div>
        <div class="box b">B</div>
        <div class="box c">C</div>
        <div class="box d">D</div>
        <div class="box e">E</div>
        <div class="box f">F</div>
    </div>
    <br />
    <div class="grid-container" style="color: #636">
        <div class="box a">A</div>
        <div class="box b">B</div>
        <div class="box c">C</div>
        <div class="box d">D</div>
        <div class="box e">E</div>
        <div class="box f">F</div>
    </div>
</body>
</html>
