<!DOCTYPE html>
<html>
<head>
<script src="../../http/tests/inspector/resources/inspector-test.js"></script>
<script>
function load() {
    window.onscreenCanvas = document.getElementById("onscreen").getContext("2d");
    window.offscreenCanvas = document.createElement("canvas").getContext("2d");
    window.cssCanvas = document.getCSSCanvasContext("2d", "css", 10, 10);

    runTest();
}

function test() {
    let suite = InspectorTest.createAsyncSuite("Canvas.requestNode");

    suite.addTestCase({
        name: "Canvas.requestNode.validCanvasId",
        description: "Get the node id for each canvas on the page.",
        test(resolve, reject) {
            let canvases = WI.canvasManager.canvases;
            let expectedLength = canvases.length;
            InspectorTest.assert(expectedLength === 3, "The page has 3 canvases.");

            let nodesMap = new Map;

            function finish() {
                let results = {};
                for (let [canvas, node] of nodesMap)
                    results[canvas.displayName] = node;

                let keys = Object.keys(results);
                InspectorTest.assert(keys.length === nodesMap.size, "No display name collisions");

                // Ensure that the test runs properly even if the canvas
                // events are sent in a different order than the above.
                keys.sort();
                for (let displayName of keys) {
                    InspectorTest.expectThat(results[displayName], `Canvas "${displayName}" has node with valid id.`);
                    InspectorTest.expectEqual(results[displayName].nodeName(), "CANVAS", `Canvas "${displayName}" has node with type "CANVAS".`);
                }

                resolve();
            }

            canvases.forEach((canvas) => {
                WI.domManager.requestDocument((documentNode) => {
                    CanvasAgent.requestNode(canvas.identifier, (error, nodeId) => {
                        if (error) {
                            reject(error);
                            return;
                        }

                        nodesMap.set(canvas, WI.domManager.nodeForId(nodeId));
                        if (nodesMap.size === expectedLength)
                            finish();
                    });
                });
            });
        }
    });

    // ------

    suite.addTestCase({
        name: "Canvas.requestNode.invalidCanvasId",
        description: "Invalid canvas identifiers should cause an error.",
        test(resolve, reject) {
            const canvasId = "DOES_NOT_EXIST";
            CanvasAgent.requestNode(canvasId, (error) => {
                InspectorTest.expectThat(error, "Should produce an error.");
                InspectorTest.log("Error: " + error);
                resolve();
            });
        }
    });

    suite.runTestCasesAndFinish();
}
</script>
<style>
    .css { background-image: -webkit-canvas(css); }
</style>
</head>
<body onload="load()">
<p>Test that CanvasAgent.requestNode can properly resolve the owner canvas node.</p>
<canvas id="onscreen"></canvas>
</body>
</html>
