<!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 = Array.from(WI.canvasManager.canvasCollection);
            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>
