<html>
<head>
<script src="../../http/tests/inspector/inspector-test.js"></script>
<script src="editor-test.js"></script>
<script>

function test()
{
    WebInspector.experimentsSettings.textEditorSmartBraces.enableForTest();

    var textEditor = InspectorTest.createTestEditor();
    textEditor.overrideViewportForTest(0, undefined, 3);
    textEditor.mimeType = "text/javascript";
    textEditor.setReadOnly(false);
    textEditor.element.focus();

    textEditor.setText("");
    textEditor.setSelection(WebInspector.TextRange.createFromLocation(0, 0));

    function dump(next)
    {
        InspectorTest.addResult(InspectorTest.textWithSelection(textEditor.text(), textEditor.selection()));
        next();
    }

    function waitAndDump(next)
    {
        setTimeout(dump.bind(this, next));
    }

    function keyDown(character)
    {
        eventSender.keyDown(character, []);
    }

    var insertText = textInputController.insertText.bind(textInputController);

    InspectorTest.runTestSuite([
        function typeFunctionName(next)
        {
            insertText("function myMax");
            waitAndDump(next);
        },

        function typeOpeningRoundBrace(next)
        {
            keyDown("(");
            dump(next);
        },

        function typeFunctionArguments(next)
        {
            insertText("a, b");
            waitAndDump(next);
        },

        function typeClosingBrace(next)
        {
            keyDown(")");
            dump(next);
        },

        function typeOpeningCurlyBrace(next)
        {
            keyDown("{");
            dump(next);
        },

        function typeEnter(next)
        {
            keyDown("\n");
            dump(next);
        },

        function typeReturnStatement(next)
        {
            insertText("return ");
            waitAndDump(next);
        },

        function typeNestedBraces(next)
        {
            keyDown("(");
            keyDown("{");
            keyDown("(");
            dump(next);
        },

        function hitBackspaceTrippleTimes(next)
        {
            keyDown("\b");
            keyDown("\b");
            keyDown("\b");
            dump(next);
        },

        function typeMathMax(next)
        {
            insertText("Math.max(a, b);");
            waitAndDump(next);
        },

        function setCursorBeforeClosingCurlyBrace(next)
        {
            textEditor.setSelection(WebInspector.TextRange.createFromLocation(2, 0));
            dump(next);
        },

        function typeInClosingCurlyBrace(next)
        {
            keyDown("}");
            dump(next);
        },

        function gotoVeryBeginning(next)
        {
            textEditor.setSelection(WebInspector.TextRange.createFromLocation(0, 0));
            dump(next);
        },

        function typeOpeningRoundAndCurlyBraces(next)
        {
            keyDown("(");
            keyDown("{");
            waitAndDump(next);
        }
    ]);
}

</script>
</head>

<body onload="runTest();">
<p>
This test checks text editor smart braces functionality.
</p>

</body>
</html>
