diff --git a/README.md b/README.md index db92db9..5d624e2 100644 --- a/README.md +++ b/README.md @@ -1,20 +1,30 @@ sideflow - a flow control extension for Selenium IDE === +Lets you do goto and while loops in the Selenium IDE Firefox add-on as well as via the _selenese_ goal in the +Maven Selenium Plugin. This is a Selenium IDE compatible port of the flow control extension from +[http://wiki.openqa.org/display/SEL/flowControl](http://wiki.openqa.org/display/SEL/flowControl) which is the older +outdated version of [https://addons.mozilla.org/en-us/firefox/addon/flow-control/](https://addons.mozilla.org/en-us/firefox/addon/flow-control/). -Lets you do goto and while loops in the Selenium IDE Firefox add-on. This is a Selenium -IDE compatible port of the flow control extension from http://wiki.openqa.org/display/SEL/flowControl. - - +![picture](http://4.bp.blogspot.com/_Vi1folaOZAs/R7N1_L5KjDI/AAAAAAAAAGQ/PyozuVCHBC4/s400/flow_control_ide.png") Requirements --- Selenium IDE v1.0.5 + +Selenium Maven Plugin v2.3 + Install --- -- Get Selenium IDE for Firefox from http://seleniumhq.org -- Launch Selenium IDE from Firefox and open the options menu -- Add the sideflow.js file to the "Selenium Core extensions (user-extensions.js)" field +__Firefox Selenium IDE__ + + * Get Selenium IDE for Firefox from [http://www.SeleniumHQ.org/projects/ide/](http://www.SeleniumHQ.org/projects/ide/) + * Launch Selenium IDE from Firefox and open the _Options_ menu + * Add the sideflow.js file to the "Selenium Core extensions (user-extensions.js)" field + +__Selenium Maven Plugin ( _selenese_ )__ + + * Install and configure your Selenium Maven Plugin in your POM + * Configure the plugin _userExtensions_ property + * Configure your execution to use the _selenese_ goal Commands --- @@ -28,7 +38,6 @@ Commands Resources --- - - [Full Documentation](http://51elliot.blogspot.com/2008/02/selenium-ide-goto.html) - Selenium HQ [SeleniumHQ](http://seleniumhq.org/) @@ -36,6 +45,7 @@ Authors --- - Andrey Yegorov - original flow control extension - Darren DeRidder - Selenium IDE port +- Paul Bors - Selenium Maven Plugin port License --- diff --git a/sideflow.js b/sideflow.js index c72e321..0979041 100644 --- a/sideflow.js +++ b/sideflow.js @@ -1,126 +1,212 @@ -var gotoLabels= {}; -var whileLabels = {}; - -// overload the original Selenium reset function -Selenium.prototype.reset = function() { - // reset the labels - this.initialiseLabels(); - // proceed with original reset code - this.defaultTimeout = Selenium.DEFAULT_TIMEOUT; - this.browserbot.selectWindow("null"); - this.browserbot.resetPopups(); -} - - -/* - * --- Initialize Conditional Elements --- * - * Run through the script collecting line numbers of all conditional elements - * There are three a results arrays: goto labels, while pairs and forEach pairs - * - */ -Selenium.prototype.initialiseLabels = function() -{ - gotoLabels = {}; - whileLabels = { ends: {}, whiles: {} }; - var command_rows = []; - var numCommands = testCase.commands.length; - for (var i = 0; i < numCommands; ++i) { - var x = testCase.commands[i]; - command_rows.push(x); +var SideFlowUtils = classCreate(); +objectExtend(SideFlowUtils.prototype, { + testCase: null, + banner: "SideFlow", + initialize: function() { }, + setTestCase: function(testCase) { + this.testCase = testCase; + }, + getTestCase: function() { + return this.testCase; + }, + getCommands: function() { + var seleniumCommands; + if(this.isIDE()) { + seleniumCommands = this.getTestCase().commands; + } else { + seleniumCommands = this.getTestCase().commandRows; + } + return seleniumCommands; + }, + isIDE: function() { + return (Application.prototype != undefined); + }, + formatMessage: function(msg, error) { + return this.banner + ((error) ? "[" + error.lineNumber + "] " : " ") + msg; + }, + debug: function(msg, error) { + LOG.debug(this.formatMessage(msg, error)); + }, + info: function(msg, error) { + LOG.info(this.formatMessage(msg, error)); + }, + warn: function(msg, error) { + LOG.warn(this.formatMessage(msg, error)); + }, + error: function(msg, error) { + LOG.error(this.formatMessage(msg, error)); + }, + throwError: function(err, error) { + throw new SeleniumError(this.formatMessage(err, error)); } - var cycles = []; - var forEachCmds = []; - for( var i = 0; i < command_rows.length; i++ ) { - if (command_rows[i].type == 'command') - switch( command_rows[i].command.toLowerCase() ) { - case "label": - gotoLabels[ command_rows[i].target ] = i; - break; - case "while": - case "endwhile": - cycles.push( [command_rows[i].command.toLowerCase(), i] ) - break; - case "foreach": - case "endforeach": - forEachCmds.push( [command_rows[i].command.toLowerCase(), i] ) - break; +}); + +var SideFlow = classCreate(); +objectExtend(SideFlow.prototype, { + gotoLabels: {}, + whileLabels: { ends: {}, whiles: {} }, + utils: null, + /* + * --- Initialize Conditional Elements --- * + * Run through the script collecting line numbers of all conditional elements + * There are three a results arrays: goto labels, while pairs and forEach pairs + */ + initialize: function(sideFlowUtils) { + this.utils = sideFlowUtils; + this.utils.debug("detected runtime = Selenium " + (this.utils.isIDE() ? "IDE" : "RC"), new Error()); + if(this.utils.isIDE()) { + this.utils.setTestCase(testCase); + } else { + this.utils.setTestCase(testFrame.getCurrentTestCase()); } - } - var i = 0; - while( cycles.length ) { - if( i >= cycles.length ) { - throw new Error( "non-matching while/endWhile found" ); + try { + var commands = this.utils.getCommands(), + command_rows = [], + cycles = [], + forEachCmds = []; + for(var i = 0; i < commands.length; ++i) { + command_rows.push(commands[i]); + } + for(var i = 0; i < command_rows.length; i++) { + if (this.utils.isIDE()) { + if((command_rows[i].type == 'command')) { + switch (command_rows[i].command.toLowerCase()) { + case "label": + this.gotoLabels[ command_rows[i].target ] = i; + break; + case "while": + case "endwhile": + cycles.push([command_rows[i].command.toLowerCase(), i]); + break; + case "foreach": + case "endforeach": + forEachCmds.push([command_rows[i].command.toLowerCase(), i]); + break; + } + } + } else { + var command = command_rows[i].trElement.cells[0].innerHTML; + var target = command_rows[i].trElement.cells[1].innerHTML; + var value = command_rows[i].trElement.cells[2].innerHTML; + switch (command.toLowerCase()) { + case "label": + this.gotoLabels[ target ] = i; + break; + case "while": + case "endwhile": + cycles.push([command.toLowerCase(), i]); + break; + case "foreach": + case "endforeach": + forEachCmds.push([command.toLowerCase(), i]); + break; + } + } + } + } catch (err) { + this.utils.error(err, new Error()); + this.utils.throwError(err, new Error()); } - switch( cycles[i][0] ) { - case "while": - if( ( i+1 < cycles.length ) && ( "endwhile" == cycles[i+1][0] ) ) { - // pair found - whileLabels.ends[ cycles[i+1][1] ] = cycles[i][1]; - whileLabels.whiles[ cycles[i][1] ] = cycles[i+1][1]; - cycles.splice( i, 2 ); - i = 0; - } else ++i; - break; - case "endwhile": - ++i; - break; + var i = 0; + while (cycles.length) { + if(i >= cycles.length) { + this.utils.throwError("non-matching while/endWhile found", new Error()); + } + switch(cycles[i][0]) { + case "while": + if(( i + 1 < cycles.length ) && ( "endwhile" == cycles[i + 1][0] )) { + // pair found + this.whileLabels.ends[ cycles[i + 1][1] ] = cycles[i][1]; + this.whileLabels.whiles[ cycles[i][1] ] = cycles[i + 1][1]; + cycles.splice(i, 2); + i = 0; + } else { + ++i; + } + break; + case "endwhile": + ++i; + break; + } + } + }, + continueFromRow: function (row_num) { + if((row_num == undefined) || (row_num == null) || (row_num < 0) || isNaN(row_num)) { + this.utils.throwError("Invalid row_num specified.", new Error()); + } + if(this.utils.isIDE()) { + this.utils.getTestCase().debugContext.debugIndex = row_num; + } else { + this.utils.getTestCase().nextCommandRowIndex = row_num + 1; } } +}); -} - -Selenium.prototype.continueFromRow = function( row_num ) -{ - if(row_num == undefined || row_num == null || row_num < 0) { - throw new Error( "Invalid row_num specified." ); - } - testCase.debugContext.debugIndex = row_num; -} +var sideFlow = null; +(function() { + // Proxy design pattern - Overwrite Selenium's reset() function and then invoke the original impl + var proxied = Selenium.prototype.reset; + Selenium.prototype.reset = function() { + sideFlow = new SideFlow(new SideFlowUtils()); + proxied.apply( this, arguments ); + }; +})(); // do nothing. simple label -Selenium.prototype.doLabel = function(){}; +Selenium.prototype.doLabel = function() { }; -Selenium.prototype.doGotoLabel = function( label ) -{ - if( undefined == gotoLabels[label] ) { - throw new Error( "Specified label '" + label + "' is not found." ); +Selenium.prototype.doGotoLabel = function(label) { + if(undefined == sideFlow.gotoLabels[label]) { + sideFlow.utils.throwError( "Specified label '" + label + "' is not found.", new Error() ); } - this.continueFromRow( gotoLabels[ label ] ); + sideFlow.continueFromRow( sideFlow.gotoLabels[label] ); }; Selenium.prototype.doGoto = Selenium.prototype.doGotoLabel; -Selenium.prototype.doGotoIf = function( condition, label ) -{ - if( eval(condition) ) this.doGotoLabel( label ); -} +Selenium.prototype.doGotoIf = function(condition, label) { + if(eval(condition)) { + this.doGotoLabel( label ); + } +}; -Selenium.prototype.doWhile = function( condition ) -{ - if( !eval(condition) ) { - var last_row = testCase.debugContext.debugIndex; - var end_while_row = whileLabels.whiles[ last_row ]; - if( undefined == end_while_row ) throw new Error( "Corresponding 'endWhile' is not found." ); - this.continueFromRow( end_while_row ); +Selenium.prototype.doWhile = function(condition) { + if(!eval(condition)) { + var last_row; + if(sideFlow.utils.isIDE()) { + last_row = sideFlow.utils.getTestCase().debugContext.debugIndex; + } else { + last_row = sideFlow.utils.getTestCase().nextCommandRowIndex - 1; + } + var end_while_row = sideFlow.whileLabels.whiles[ last_row ]; + if((undefined == end_while_row) || isNaN(end_while_row)) { + sideFlow.utils.throwError( "Corresponding 'endWhile' is not found.", new Error() ); + } + sideFlow.continueFromRow( end_while_row ); } -} +}; -Selenium.prototype.doEndWhile = function() -{ - var last_row = testCase.debugContext.debugIndex; - var while_row = whileLabels.ends[ last_row ] - 1; - if( undefined == while_row ) throw new Error( "Corresponding 'While' is not found." ); - this.continueFromRow( while_row ); -} +Selenium.prototype.doEndWhile = function() { + var last_row; + if(sideFlow.utils.isIDE()) { + last_row = sideFlow.utils.getTestCase().debugContext.debugIndex; + } else { + last_row = sideFlow.utils.getTestCase().nextCommandRowIndex - 1; + } + var while_row = sideFlow.whileLabels.ends[ last_row ] - 1; + if((undefined == while_row) || isNaN(while_row)) { + sideFlow.utils.throwError( "Corresponding 'While' is not found.", new Error() ); + } + sideFlow.continueFromRow( while_row ); +}; -Selenium.prototype.doPush= function(value, varName) -{ +Selenium.prototype.doPush = function(value, varName) { if(!storedVars[varName]) { storedVars[varName] = new Array(); - } + } if(typeof storedVars[varName] !== 'object') { - throw new Error("Cannot push value onto non-array " + varName); + sideFlow.utils.throwError("Cannot push value onto non-array " + varName, new Error()); } else { storedVars[varName].push(value); } -} +}; \ No newline at end of file