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

    let mainFrame = WI.frameResourceManager.mainFrame;
    let childFrames = mainFrame.childFrameCollection.toArray();
    InspectorTest.expectEqual(childFrames.length, 1, "Page should have a subframe.");

    const highlightConfig = {
        showInfo: true,
        contentColor: {r: 255, g: 255, b: 255},
        paddingColor: {r: 255, g: 255, b: 255},
        borderColor: {r: 255, g: 255, b: 255},
        marginColor: {r: 255, g: 255, b: 255},
    };

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

    function dumpHighlight(callback) {
        getHighlight((highlightObjectPayload) => {
            InspectorTest.expectEqual(highlightObjectPayload.length, 1, "Should be one highlighted node.");
            InspectorTest.log("Highlighted Element Data: " + JSON.stringify(highlightObjectPayload[0].elementData));
            callback();
        });
    }


    let mainFrameDocumentNodeId, mainFrameTargetNode;
    let childFrameDocumentNodeId, childFrameTargetNode;

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

    suite.addTestCase({
        name: "MainFrameNodeViaNodeId",
        description: "Should highlight a node in the main frame using node id.",
        test(resolve, reject) {
            WI.domTreeManager.querySelector(mainFrameDocumentNodeId, "#id-one", function(nodeId) {
                mainFrameTargetNode = WI.domTreeManager.nodeForId(nodeId);
                DOMAgent.highlightNode(highlightConfig, mainFrameTargetNode.id, undefined, (error) => {
                    InspectorTest.assert(!error, "Should not have an error.");
                    dumpHighlight(resolve);
                });
            });
        }
    });

    suite.addTestCase({
        name: "ChildFrameNodeViaNodeId",
        description: "Should highlight a node in the child frame using node id.",
        test(resolve, reject) {
            WI.domTreeManager.querySelector(childFrameDocumentNodeId, "#id-one", function(nodeId) {
                childFrameTargetNode = WI.domTreeManager.nodeForId(nodeId);
                DOMAgent.highlightNode(highlightConfig, childFrameTargetNode.id, undefined, (error) => {
                    InspectorTest.assert(!error, "Should not have an error.");
                    dumpHighlight(resolve);
                });
            });
        }
    });

    suite.addTestCase({
        name: "MainFrameNodeViaObjectId",
        description: "Should highlight a node in the main frame using object id.",
        test(resolve, reject) {
            WI.RemoteObject.resolveNode(mainFrameTargetNode, "test").then((remoteObject) => {
                DOMAgent.highlightNode(highlightConfig, undefined, remoteObject.objectId, (error) => {
                    InspectorTest.assert(!error, "Should not have an error.");
                    dumpHighlight(resolve);
                });
            })
            .catch(reject);
        }
    });

    suite.addTestCase({
        name: "ChildFrameNodeViaObjectId",
        description: "Should highlight a node in the child frame using object id.",
        test(resolve, reject) {
            WI.RemoteObject.resolveNode(childFrameTargetNode, "test").then((remoteObject) => {
                DOMAgent.highlightNode(highlightConfig, undefined, remoteObject.objectId, (error) => {
                    InspectorTest.assert(!error, "Should not have an error.");
                    dumpHighlight(resolve);
                });
            })
            .catch(reject);
        }
    });

    // ------

    suite.addTestCase({
        name: "MissingNodeAndObjectIdShouldError",
        description: "Missing identifiers should cause an error.",
        async test() {
            await InspectorTest.expectException(async () => {
                await DOMAgent.highlightNode(highlightConfig, undefined, undefined);
            });
        }
    });

    suite.addTestCase({
        name: "BadNodeId",
        description: "Bad node id should cause an error.",
        async test() {
            await InspectorTest.expectException(async () => {
                await DOMAgent.highlightNode(highlightConfig, 9999999, undefined);
            });
        }
    });

    suite.addTestCase({
        name: "BadObjectId",
        description: "Bad object id should cause an error.",
        async test() {
            await InspectorTest.expectException(async () => {
                await DOMAgent.highlightNode(highlightConfig, undefined, "bad-object-id");
            });
        }
    });

    WI.domTreeManager.requestDocument((documentNode) => {
        mainFrameDocumentNodeId = documentNode.id;
        RuntimeAgent.evaluate.invoke({expression: "document", objectGroup: "test", contextId: childFrames[0].pageExecutionContext.id}, (error, remoteObjectPayload) => {
            let remoteObject = WI.RemoteObject.fromPayload(remoteObjectPayload)
            remoteObject.pushNodeToFrontend((documentNodeId) => {
                childFrameDocumentNodeId = documentNodeId

                suite.runTestCasesAndFinish();
            });
        })
    });
}
</script>
</head>
<body onload="runTest()">
    <p>Tests for the DOM.highlightNode command.</p>
    <div style="width: 500px; height: 500px">
        <div class="class-one" style="width: 10px; height: 20px"></div>
        <div id="id-one" class="class-two" style="width:100px; height: 200px"></div>
        <iframe class="class-one" src="resources/highlight-iframe.html"></iframe>
    </div>
</body>
</html>
