    /*

    Siesta 5.3.0
    Copyright(c) 2009-2019 Bryntum AB
    https://bryntum.com/contact
    https://bryntum.com/products/siesta/license

    */
    /**

    @class Siesta.Test.Action.Eval
    @extends Siesta.Test.Action

    This action can be included in the `t.chain` steps only with a plain string. Siesta will examine the passed string,
    and call an apropriate method of the test class. String should have the following format:

        methodName(params)

    Method name is anything until the first parenthes. Method name may have an optional prefix `t.`.
    Everything in between of outermost parentheses will be treated as parameters for method call. For example:

        t.chain(
            // string should look like a usual method call,
            // but arguments can't reference any variables
            // strings should be quoted, to include quoting symbol in string use double slash: \\
            't.click("combo[type=some\\"Type] => .x-form-trigger")',

            // leading "t." is optional, but quoting is not
            'waitForComponent("combo[type=someType]")',

            // JSON objects are ok, but they should be a valid JSON - ie object properties should be quoted
            'myClick([ 10, 10 ], { "foo" : "bar" })',
        )

    * **Note** You can pass the JSON objects as arguments, but they should be serialized as valid JSON - ie object properties should be quoted.

    * **Note** A callback for next step in chain will be always appended to provided parameters. Make sure it is placed in a correct spot!
    For example if method signature is `t.someMethod(param1, param2, callback)` and you are calling this method as:

        t.chain(
            `t.someMethod("text")`
        )
    it will fail - callback will be provided in place of `param2`. Instead call it as:

        t.chain(
            `t.someMethod("text", null)`
        )

    This action may save you few keystrokes, when you need to perform some action with static arguments (known prior the action).

    */
    Class('Siesta.Test.Action.Eval', {

        isa         : Siesta.Test.Action,

        has : {
            /**
             * @cfg {Object} options
             *
             * Any options that will be used when simulating the event. For information about possible
             * config options, please see: <https://developer.mozilla.org/en-US/docs/DOM/event.initMouseEvent>
             */
            actionString          : null
        },

        methods : {

            process : function () {
                var test            = this.test
                var parsed          = this.parseActionString(this.actionString)

                if (parsed.error) {
                    test.fail(parsed.error)
                    this.next()
                    return
                }

                var methodName      = parsed.methodName

                if (!methodName || test.typeOf(test[ methodName ]) != 'Function') {
                    test.fail(Siesta.Resource("Siesta.Test.Action.Eval", 'invalidMethodNameText') + methodName)
                    this.next()
                    return
                }

                parsed.params.push(this.next)

                test[ methodName ].apply(test, parsed.params)
            },

            parseActionString : function (actionString) {
                var match           = /^\s*(.+?)\(\s*(.*)\s*\)\s*$/.exec(actionString)

                if (!match) return {
                    error       : Siesta.Resource("Siesta.Test.Action.Eval", 'wrongFormatText') + actionString
                }

                var methodName      = match[ 1 ].replace(/^t\./, '')

                try {
                    var params      = JSON.parse('[' + match[ 2 ] + ']')
                } catch (e) {
                    return {
                        error       : Siesta.Resource("Siesta.Test.Action.Eval", 'parseErrorText') + match[ 2 ]
                    }
                }

                return {
                    methodName      : methodName,
                    params          : params
                }
            }
        }
    });