<html>
<head>
<script src="../../http/tests/inspector/inspector-test.js"></script>
<script src="../../http/tests/inspector/debugger-test.js"></script>
<script src="../../http/tests/inspector/live-edit-test.js"></script>
<script src="resources/edit-me.js"></script>
<script src="resources/edit-me-syntax-error.js"></script>
<script src="resources/edit-me-when-paused.js"></script>

<script>

function test()
{
    var panel = WebInspector.showPanel("scripts");  

    InspectorTest.runDebuggerTestSuite([
        function testLiveEdit(next)
        {
            InspectorTest.showScriptSource("edit-me.js", didShowScriptSource);

            function didShowScriptSource(sourceFrame)
            {
                replaceInSource(sourceFrame, "return 0;", "return \"live-edited string\";", didEditScriptSource);
            }

            function didEditScriptSource()
            {
                InspectorTest.evaluateInPage("f()", didEvaluateInPage)
            }

            function didEvaluateInPage(result)
            {
                InspectorTest.assertEquals("live-edited string", result.description, "edited function returns wrong result");
                InspectorTest.dumpSourceFrameContents(panel.visibleView);
                next();
            }
        },

        function testLiveEditSyntaxError(next)
        {
            InspectorTest.showScriptSource("edit-me-syntax-error.js", didShowScriptSource);

            function didShowScriptSource(sourceFrame)
            {
                InspectorTest.replaceInSource(sourceFrame, ",\"I'm good\"", "\"I'm good\"");
                InspectorTest.dumpSourceFrameContents(panel.visibleView);
                next();
            }
        },

        function testLiveEditWhenPaused(next)
        {
            InspectorTest.showScriptSource("edit-me-when-paused.js", didShowScriptSource);

            function didShowScriptSource(sourceFrame)
            {
                InspectorTest.waitUntilPaused(paused);
                InspectorTest.evaluateInPage("f1()", didEvaluateInPage);
            }

            function paused(callFrames)
            {
                replaceInSource(panel.visibleView, "return 1;", "return 2;\n\n\n\n", didEditScriptSource);
            }

            function didEditScriptSource()
            {
                InspectorTest.resumeExecution();
            }

            function didEvaluateInPage(result)
            {
                InspectorTest.assertEquals("3", result.description, "edited function returns wrong result");
                next();
            }
        },

        function testNoCrashWhenOnlyOneFunctionOnStack(next)
        {
            InspectorTest.showScriptSource("edit-me-when-paused.js", didShowScriptSource);

            function didShowScriptSource(sourceFrame)
            {
                InspectorTest.waitUntilPaused(paused);
                InspectorTest.evaluateInPage("setTimeout(f1, 0)");
            }

            function paused(callFrames)
            {
                InspectorTest.captureStackTrace(callFrames);
                replaceInSource(panel.visibleView, "debugger;", "debugger;\n", didEditScriptSource);
            }

            function didEditScriptSource()
            {
                InspectorTest.resumeExecution(InspectorTest.waitUntilPaused.bind(InspectorTest, InspectorTest.resumeExecution.bind(InspectorTest, next)));
            }
        },

        function testBreakpointsUpdated(next)
        {
            InspectorTest.showScriptSource("edit-me.js", didShowScriptSource);

            function didShowScriptSource(sourceFrame)
            {
                InspectorTest.addSniffer(sourceFrame, "_addBreakpointDecoration", breakpointAdded);
                InspectorTest.setBreakpoint(sourceFrame, 2, "", true);
            }

            function breakpointAdded()
            {
                replaceInSource(panel.visibleView, "function f()", "function newFunctionCreatedWithLiveEdit()\n{\n}\nfunction f()", didEditScriptSource);
            }

            function didEditScriptSource()
            {
                var breakpoints = panel.visibleView._breakpoints;
                for (var lineNumber in breakpoints)
                    InspectorTest.assertEquals("5", lineNumber);
                next();
            }
        }
    ]);

    function replaceInSource(sourceFrame, string, replacement, callback)
    {
        InspectorTest.addSniffer(WebInspector.debuggerModel, "_didEditScriptSource", callback);
        InspectorTest.replaceInSource(sourceFrame, string, replacement);
        InspectorTest.commitSource(sourceFrame);
        
    }
};

</script>

</head>

<body onload="runTest()">
<p>Tests live edit feature.</p>

</body>
</html>
