var REPL_INITIAL_SUGGESTIONS = [ 'element(by.id(\'\'))', 'element(by.css(\'\'))', 'element(by.name(\'\'))', 'element(by.binding(\'\'))', 'element(by.xpath(\'\'))', 'element(by.tagName(\'\'))', 'element(by.className(\'\'))' ]; /** * Repl to interactively run commands in the context of the test. * * @param {Client} node debugger client. * @constructor */ var CommandRepl = function(client) { this.client = client; this.prompt = '> '; }; /** * Eval function for processing a single step in repl. * Call callback with the result when complete. * * @public * @param {string} expression * @param {function} callback */ CommandRepl.prototype.stepEval = function(expression, callback) { expression = expression.replace(/"/g, '\\\"'); var expr = 'browser.debugHelper.dbgCodeExecutor.execute("' + expression + '")'; this.evaluate_(expr, callback); }; /** * Autocomplete user entries. * Call callback with the suggestions. * * @public * @param {string} line Initial user entry * @param {function} callback */ CommandRepl.prototype.complete = function(line, callback) { if (line === '') { callback(null, [REPL_INITIAL_SUGGESTIONS, '']); } else { // TODO(juliemr): This is freezing the program! line = line.replace(/"/g, '\\\"'); var expr = 'browser.debugHelper.dbgCodeExecutor.complete("' + line + '")'; this.evaluate_(expr, function(err, res) { // Result is a JSON representation of the autocomplete response. var result = res === undefined ? undefined : JSON.parse(res); callback(err, result); }); } }; /** * Helper function to evaluate an expression remotely, and callback with * the result. The expression can be a promise, in which case, the method * will wait for the result and callback with the resolved value. * * @private * @param {string} expression Expression to evaluate * @param {function} callback */ CommandRepl.prototype.evaluate_ = function(expression, callback) { var self = this; var onbreak_ = function() { self.client.req({ command: 'evaluate', arguments: { frame: 0, maxStringLength: 1000, expression: 'browser.debugHelper.dbgCodeExecutor.resultReady()' } }, function(err, res) { if (err) { throw new Error('Error while checking if debugger expression result was ready.' + 'Expression: ' + expression + ' Error: ' + err); } // If code finished executing, get result. if (res.value) { self.client.req({ command: 'evaluate', arguments: { frame: 0, maxStringLength: -1, expression: 'browser.debugHelper.dbgCodeExecutor.getResult()' } }, function(err, res) { try { callback(err, res.value); } catch (e) { callback(e, undefined); } self.client.removeListener('break', onbreak_); }); } else { // If we need more loops for the code to finish executing, continue // until the next execute step. self.client.reqContinue(function() { // Intentionally blank. }); } }); }; this.client.on('break', onbreak_); this.client.req({ command: 'evaluate', arguments: { frame: 0, maxStringLength: 1000, expression: expression } }, function() { self.client.reqContinue(function() { // Intentionally blank. }); }); }; module.exports = CommandRepl;