<html>
<head>
<script src="../../http/tests/inspector/inspector-test.js"></script>
<script src="../../http/tests/inspector/extensions-test.js"></script>
<script type="text/javascript">

function initialize_extensionsSidebarTest()
{
    InspectorTest.dumpSidebarContent = function(callback)
    {
        var sidebar = InspectorTest._extensionSidebar();
        InspectorTest.runAfterPendingDispatches(function() {
            InspectorTest.addResult("Sidebar content: " + sidebar.bodyElement.textContent);
            callback();
        });
    }

    InspectorTest.expandSidebar = function(callback)
    {
        var sidebar = InspectorTest._extensionSidebar();
        InspectorTest.runAfterPendingDispatches(function() {
            sidebar.expand();
            callback();
        });
    }

    InspectorTest._extensionSidebar = function()
    {
        var sidebarPanes = WebInspector.panel("elements").sidebarPanes;
        // the sidebar of interest is presumed to always be last.
        return sidebarPanes[Object.keys(sidebarPanes).pop()];
    }
}

function extension_testSidebarSetPage(nextTest)
{
    function onSidebarCreated(sidebar)
    {
        output("Sidebar created");
        dumpObject(sidebar);
        function onShown()
        {
            sidebar.onShown.removeListener(onShown);
            nextTest();
        }
        sidebar.onShown.addListener(onShown);
        var basePath = location.pathname.replace(/\/[^/]*$/, "/");
        sidebar.setPage(basePath + "extension-sidebar.html");
        extension_showPanel("elements", extension_expandSidebar);
    }
    webInspector.panels.elements.createSidebarPane("Test Sidebar", onSidebarCreated);
}

function extension_dumpSidebarContent(nextTest)
{
    evaluateOnFrontend("InspectorTest.dumpSidebarContent(reply);", nextTest);
}

function extension_expandSidebar(callback)
{
    evaluateOnFrontend("InspectorTest.expandSidebar(reply);", callback);
}

function extension_testSidebarSetObject(nextTest)
{
    function onSidebarCreated(sidebar)
    {
        output("Watch sidebar created, callback arguments dump follows:");
        dumpObject(Array.prototype.slice.call(arguments));
        sidebar.setObject({
            f0: "object",
            f1: undefined,
            f2: null,
            f3: {},
            f4: [],
            f5: ["aa", "bb", "cc"],
            f6: { f60: 42, f61: "foo", f62: [] },
            f7: 42
        }, null, extension_dumpSidebarContent.bind(this, nextTest));
    }
    webInspector.panels.elements.createSidebarPane("Watch Test: Object", onSidebarCreated);
}

function extension_testSidebarSetExpression(nextTest)
{
    function onSidebarCreated(sidebar)
    {
        function expression()
        {
            document.body.testProperty = 'foo';
            return {
                f0: 'expression',
                f1: undefined,
                f2: null,
                f3: {},
                f4: [],
                f5: ["aa", "bb", "cc"],
                f6: { f60: 42, f61: "foo", f62: [] },
                f7: 42,
                f8: window.location,
                f9: document.body.children,
                f10: function() {},
                f11: $0.testProperty
            };
        }
        // Do an extra round-trip to the inspected page to assure inspect()'s round-trip to
        // front-end is complete and $0 is properly updated with currently inspected node.
        webInspector.inspectedWindow.eval("", function() {
            sidebar.setExpression("(" + expression.toString() + ")();", "title", extension_dumpSidebarContent.bind(this, nextTest));
        });
    }
    webInspector.inspectedWindow.eval("inspect(document.body)", function() {
        webInspector.panels.elements.createSidebarPane("Watch Test: Expression", onSidebarCreated);
    });
}

function extension_testSidebarPageReplacedWithObject(nextTest)
{
     var basePath = location.pathname.replace(/\/[^/]*$/, "/");
     var sidebar;

     function onSidebarCreated(aSidebar)
     {
         sidebar = aSidebar;
         sidebar.onShown.addListener(onShown);
         sidebar.setPage(basePath + "extension-sidebar.html");
         extension_showPanel("elements", extension_expandSidebar);
     }
     var didSetObject = false;
     function onShown(frame)
     {
         output("Got onShown(), frame " + (frame ? "defined" : "not defined"));
         if (!didSetObject) {
             didSetObject = true;
             sidebar.setObject({ foo: 'bar' });
         } else {
            sidebar.onShown.removeListener(onShown);
            nextTest();
         }
     }
     webInspector.panels.elements.createSidebarPane("Sidebar Test: replace page with object", onSidebarCreated);
}

</script>
</head>
<body onload="runTest()">
<p>Tests sidebars in WebInspector extensions API</p>
</body>
</html>
