commit/galaxy-central: carlfeberhard: browser tests: remove error handlers inside tryStepsCatch; add HDA state tests; begin moving selectors and text to central locations
1 new commit in galaxy-central: https://bitbucket.org/galaxy/galaxy-central/commits/07262aa19788/ changeset: 07262aa19788 user: carlfeberhard date: 2013-03-12 22:32:41 summary: browser tests: remove error handlers inside tryStepsCatch; add HDA state tests; begin moving selectors and text to central locations affected #: 6 files diff -r c03c46ced8cc0ac2f36d92ac093684e6cf828609 -r 07262aa197881ac0d69be70987f8fb89e0564570 test/casperjs/anon-history-tests.js --- a/test/casperjs/anon-history-tests.js +++ b/test/casperjs/anon-history-tests.js @@ -39,23 +39,22 @@ spaceghost.info( 'Will use fixtureData.testUser: ' + email ); } -var galaxyCookieName = 'galaxysession', - - nameSelector = 'div#history-name', - unnamedName = 'Unnamed history', - subtitleSelector = 'div#history-subtitle-area', - initialSizeStr = '0 bytes', - tagIconSelector = '#history-tag.icon-button', - annoIconSelector = '#history-annotate.icon-button', - //emptyMsgSelector = '#emptyHistoryMessage'; - emptyMsgSelector = '.infomessagesmall', - emptyMsgStr = "Your history is empty. Click 'Get Data' on the left pane to start", - - tooltipSelector = '.bs-tooltip', - anonNameTooltip = 'You must be logged in to edit your history name', +var tooltipSelector = '.bs-tooltip', editableTextClass = 'editable-text', - editableTextInputSelector = 'input#renaming-active'; + editableTextInputSelector = 'input#renaming-active', + + galaxyCookieName = 'galaxysession'; + + unnamedName = spaceghost.historypanel.data.text.history.newName, + nameSelector = spaceghost.historypanel.data.selectors.history.name, + subtitleSelector = spaceghost.historypanel.data.selectors.history.subtitle, + initialSizeStr = spaceghost.historypanel.data.text.history.newSize, + tagIconSelector = spaceghost.historypanel.data.selectors.history.tagIcon, + annoIconSelector = spaceghost.historypanel.data.selectors.history.annoIcon, + emptyMsgSelector = spaceghost.historypanel.data.selectors.history.emptyMsg, + emptyMsgStr = spaceghost.historypanel.data.text.history.emptyMsg, + anonNameTooltip = spaceghost.historypanel.data.text.anonymous.tooltips.name; var historyFrameInfo = {}, testUploadInfo = {}; @@ -111,8 +110,8 @@ this.test.assertDoesntExist( tagIconSelector, 'Tag icon button not found' ); this.test.assertDoesntExist( annoIconSelector, 'Annotation icon button not found' ); + this.test.assertExists( emptyMsgSelector, emptyMsgSelector + ' exists' ); this.test.comment( "A message about the current history being empty should be displayed" ); - this.test.assertExists( emptyMsgSelector, emptyMsgSelector + ' exists' ); this.test.assertVisible( emptyMsgSelector, 'Empty history message is visible' ); this.test.assertSelectorHasText( emptyMsgSelector, emptyMsgStr, 'Message contains "' + emptyMsgStr + '"' ); diff -r c03c46ced8cc0ac2f36d92ac093684e6cf828609 -r 07262aa197881ac0d69be70987f8fb89e0564570 test/casperjs/casperjs_runner.py --- a/test/casperjs/casperjs_runner.py +++ b/test/casperjs/casperjs_runner.py @@ -344,6 +344,15 @@ self.run_js_script( 'anon-history-tests.js' ) +class Test_04_HDAs( CasperJSTestCase ): + """(Minimal) casperjs tests for tools. + """ + def test_00_HDA_states( self ): + """Test structure rendering of HDAs in all the possible HDA states + """ + self.run_js_script( 'hda-state-tests.js' ) + + # ==================================================================== MAIN if __name__ == '__main__': diff -r c03c46ced8cc0ac2f36d92ac093684e6cf828609 -r 07262aa197881ac0d69be70987f8fb89e0564570 test/casperjs/hda-state-tests.js --- /dev/null +++ b/test/casperjs/hda-state-tests.js @@ -0,0 +1,140 @@ +// have to handle errors here - or phantom/casper won't bail but _HANG_ +try { + var utils = require( 'utils' ), + xpath = require( 'casper' ).selectXPath, + format = utils.format, + + //...if there's a better way - please let me know, universe + scriptDir = require( 'system' ).args[3] + // remove the script filename + .replace( /[\w|\.|\-|_]*$/, '' ) + // if given rel. path, prepend the curr dir + .replace( /^(?!\/)/, './' ), + spaceghost = require( scriptDir + 'spaceghost' ).create({ + // script options here (can be overridden by CLI) + //verbose: true, + //logLevel: debug, + scriptDir: scriptDir + }); + + spaceghost.start(); + +} catch( error ){ + console.debug( error ); + phantom.exit( 1 ); +} + + +// =================================================================== +/* TODO: + currently going to fake states via JS + - better if we can capture actual hdas in these states + - easier said than done - API? +*/ +// =================================================================== globals and helpers +var email = spaceghost.user.getRandomEmail(), + password = '123456'; +if( spaceghost.fixtureData.testUser ){ + email = spaceghost.fixtureData.testUser.email; + password = spaceghost.fixtureData.testUser.password; + spaceghost.info( 'Will use fixtureData.testUser: ' + email ); +} + +var newHistoryName = "Test History", + historyFrameInfo = {}, + filepathToUpload = '../../test-data/1.txt', + possibleHDAStates = [], + testUploadInfo = {}; + +// ------------------------------------------------------------------- set up +// start a new user +spaceghost.user.loginOrRegisterUser( email, password ); +// ??: why is a reload needed here? If we don't, loggedInAs === '' ... +spaceghost.thenOpen( spaceghost.baseUrl, function(){ + var loggedInAs = spaceghost.user.loggedInAs(); + this.test.assert( loggedInAs === email, 'loggedInAs() matches email: "' + loggedInAs + '"' ); +}); + +// grab the history frame bounds for mouse later tests +spaceghost.then( function(){ + historyFrameInfo = this.getElementInfo( 'iframe[name="galaxy_history"]' ); + //this.debug( 'historyFrameInfo:' + this.jsonStr( historyFrameInfo ) ); +}); + +// upload a file +spaceghost.then( function upload(){ + spaceghost.tools.uploadFile( filepathToUpload, function uploadCallback( _uploadInfo ){ + testUploadInfo = _uploadInfo; + this.info( 'testUploadInfo:' + this.jsonStr( testUploadInfo ) ); + }); +}); + +spaceghost.then( function getHDAStates(){ + this.withFrame( this.selectors.frames.history, function(){ + var model = this.evaluate( function(){ + return Galaxy.currHistoryPanel.model.hdas.at( 0 ).attributes; + }); + this.info( 'model:' + this.jsonStr( model ) ); + }); +}); + +spaceghost.then( function checkNewState(){ + this.test.comment( 'HDAs in the "new" state should be well formed' ); + + this.withFrame( this.selectors.frames.history, function(){ + // set state directly through model + //TODO: not ideal + this.evaluate( function(){ + return Galaxy.currHistoryPanel.model.hdas.at( 0 ).set( 'state', 'new' ); + }); + // wait for re-render + this.wait( 500, function(){ + var uploadSelector = '#' + testUploadInfo.hdaElement.attributes.id; + this.test.assertVisible( uploadSelector, 'HDA is visible' ); + + // should have proper title and hid + var titleSelector = uploadSelector + ' .historyItemTitle'; + this.test.assertVisible( titleSelector, 'HDA title is visible' ); + this.test.assertSelectorHasText( titleSelector, testUploadInfo.name, + 'HDA has proper title' ); + this.test.assertSelectorHasText( titleSelector, testUploadInfo.hid, + 'HDA has proper hid' ); + + // should have the new state class + var newStateClass = 'historyItem-new', + uploadElement = this.getElementInfo( uploadSelector ); + this.test.assert( uploadElement.attributes['class'].indexOf( newStateClass ) !== -1, + 'HDA has new state class' ); + + // since we're using css there's no great way to test this + //var stateIconSelector = uploadSelector + ' .state-icon'; + //this.test.assertVisible( stateIconSelector, 'HDA has proper hid' ); + + // should NOT have any of the three, main buttons + var buttonSelector = uploadSelector + ' .historyItemButtons a'; + this.test.assertDoesntExist( buttonSelector, 'No display, edit, or delete buttons' ); + + // expand and check the body + this.click( titleSelector ); + this.wait( 500, function(){ + var bodySelector = uploadSelector + ' .historyItemBody'; + this.test.assertVisible( bodySelector, 'HDA body is visible (after expanding)' ); + + var expectedBodyText = 'This is a new dataset'; + this.test.assertSelectorHasText( bodySelector, expectedBodyText, + 'HDA body has text: ' + expectedBodyText ); + + // restore to collapsed + this.click( titleSelector ); + }); + }); + }); +}); + +// =================================================================== TESTS + + +// =================================================================== +spaceghost.run( function(){ + this.test.done(); +}); diff -r c03c46ced8cc0ac2f36d92ac093684e6cf828609 -r 07262aa197881ac0d69be70987f8fb89e0564570 test/casperjs/history-panel-tests.js --- a/test/casperjs/history-panel-tests.js +++ b/test/casperjs/history-panel-tests.js @@ -24,7 +24,6 @@ phantom.exit( 1 ); } - // =================================================================== /* TODO: possibly break this file up @@ -38,41 +37,36 @@ spaceghost.info( 'Will use fixtureData.testUser: ' + email ); } -var nameSelector = 'div#history-name', - unnamedName = 'Unnamed history', - subtitleSelector = 'div#history-subtitle-area', - initialSizeStr = '0 bytes', - tagIconSelector = '#history-tag.icon-button', - annoIconSelector = '#history-annotate.icon-button', - emptyMsgSelector = '.infomessagesmall', - emptyMsgStr = "Your history is empty. Click 'Get Data' on the left pane to start", +// selectors and labels +var nameSelector = spaceghost.historypanel.data.selectors.history.name, + subtitleSelector = spaceghost.historypanel.data.selectors.history.subtitle, + unnamedName = spaceghost.historypanel.data.text.history.newName, + initialSizeStr = spaceghost.historypanel.data.text.history.newSize, + tagIconSelector = spaceghost.historypanel.data.selectors.history.tagIcon, + annoIconSelector = spaceghost.historypanel.data.selectors.history.annoIcon, + emptyMsgSelector = spaceghost.historypanel.data.selectors.history.emptyMsg, + emptyMsgStr = spaceghost.historypanel.data.text.history.emptyMsg, + wrapperOkClassName = spaceghost.historypanel.data.selectors.hda.wrapper.stateClasses.ok, + tagAreaSelector = spaceghost.historypanel.data.selectors.history.tagArea, + annoAreaSelector = spaceghost.historypanel.data.selectors.history.annoArea, + nameTooltip = spaceghost.historypanel.data.text.history.tooltips.name, tooltipSelector = '.bs-tooltip', - nameTooltip = 'Click to rename history', editableTextClass = 'editable-text', editableTextInputSelector = 'input#renaming-active', - wrapperOkClassName = 'historyItem-ok', - - tagAreaSelector = '#history-tag-area', - annoAreaSelector = '#history-annotation-area', refreshButtonSelector = 'a#history-refresh-button', refreshButtonIconSelector = 'span.fa-icon-refresh', refreshButtonHref = '/history', - //historyOptionsButtonSelector = '#history-options-button', - //historyOptionsButtonIconSelector = 'span.fa-icon-cog', includeDeletedOptionsLabel = spaceghost.historyoptions.data.labels.options.includeDeleted; -function historyOptionXpathByLabel( label ){ - return xpath( '//ul[@id="history-options-button-menu"]/li/a[text()[contains(.,"' + label + '")]]' ); -} - +// local var newHistoryName = "Test History", filepathToUpload = '../../test-data/1.txt', historyFrameInfo = {}, - testUploadInfo = {}; + uploadInfo = {}; // =================================================================== TESTS @@ -184,7 +178,7 @@ // ------------------------------------------------------------------- check structure of NON empty history // upload file: 1.txt spaceghost.then( function upload(){ - this.test.comment( 'should be able to upload files' ); + this.test.comment( 'uploaded file should appear in history' ); spaceghost.tools.uploadFile( filepathToUpload, function uploadCallback( _uploadInfo ){ this.debug( 'uploaded HDA info: ' + this.jsonStr( _uploadInfo ) ); var hasHda = _uploadInfo.hdaElement, @@ -224,27 +218,21 @@ // ------------------------------------------------------------------- tags // keeping this light here - better for it's own test file +//TODO: check tooltips spaceghost.then( function openTags(){ this.test.comment( 'tag area should open when the history panel tag icon is clicked' ); this.withFrame( this.selectors.frames.history, function(){ + this.capture( 'tag-area.png' ); this.mouseEvent( 'click', tagIconSelector ); this.wait( 1000, function(){ this.test.assertVisible( tagAreaSelector, 'Tag area is now displayed' ); }); }); }); -spaceghost.then( function closeTags(){ - this.test.comment( 'tag area should close when the history panel tag icon is clicked again' ); - this.withFrame( this.selectors.frames.history, function(){ - this.mouseEvent( 'click', tagIconSelector ); - this.wait( 1000, function(){ - this.test.assertNotVisible( tagAreaSelector, 'Tag area is now hidden' ); - }); - }); -}); // ------------------------------------------------------------------- annotation // keeping this light here - better for it's own test file +//TODO: check tooltips spaceghost.then( function openAnnotation(){ this.test.comment( 'annotation area should open when the history panel annotation icon is clicked' ); this.withFrame( this.selectors.frames.history, function(){ @@ -346,7 +334,8 @@ this.withFrame( this.selectors.frames.history, function(){ this.waitForSelector( nameSelector, function(){ //TODO: to conv. fn - this.click( '#' + uploadInfo.hdaElement.attributes.id + ' .historyItemUndelete' ); + this.click( '#' + uploadInfo.hdaElement.attributes.id + + ' ' + this.historypanel.data.selectors.history.undeleteLink ); }); }); }); diff -r c03c46ced8cc0ac2f36d92ac093684e6cf828609 -r 07262aa197881ac0d69be70987f8fb89e0564570 test/casperjs/modules/historypanel.js --- a/test/casperjs/modules/historypanel.js +++ b/test/casperjs/modules/historypanel.js @@ -31,7 +31,6 @@ */ // =================================================================== INTERNAL - // =================================================================== API (external) /** Find the casper element info of the hda wrapper given the hda title and hid. * NOTE: if more than one is found, will return the first found. @@ -46,6 +45,7 @@ wrapperInfo = null; //NOTE: depends on jquery + //TODO: move to xpath wrapperInfo = spaceghost.evaluate( function( titleContains ){ // find the title, then the wrapper (2 containers up) var $title = $( '.historyItemTitle:contains(' + titleContains + ')' ); @@ -199,3 +199,54 @@ }); return spaceghost; }; + + +// =================================================================== SELECTORS +//TODO: data is not a very good name +HistoryPanel.prototype.data = { + selectors : { + history : { + name : 'div#history-name', + subtitle : 'div#history-subtitle-area', + tagIcon : '#history-tag.icon-button', + tagArea : '#history-tag-area', + annoIcon : '#history-annotate.icon-button', + annoArea : '#history-annotation-area', + emptyMsg : '.infomessagesmall', + undeleteLink : '.historyItemUndelete' + }, + hda : { + wrapper : { + stateClasses : { + prefix : 'historyItem-', + ok : 'historyItem-ok' + } + } + } + }, + labels : { + history : { + }, + hda : { + } + }, + text : { + anonymous : { + tooltips : { + name : 'You must be logged in to edit your history name' + } + }, + history : { + tooltips : { + name : 'Click to rename history', + tagIcon : 'Edit history tags', + annoIcon : 'Edit history annotation' + }, + newName : 'Unnamed history', + newSize : '0 bytes', + emptyMsg : "Your history is empty. Click 'Get Data' on the left pane to start" + }, + hda : { + } + } +}; diff -r c03c46ced8cc0ac2f36d92ac093684e6cf828609 -r 07262aa197881ac0d69be70987f8fb89e0564570 test/casperjs/spaceghost.js --- a/test/casperjs/spaceghost.js +++ b/test/casperjs/spaceghost.js @@ -120,7 +120,7 @@ // save errors for later output (needs to go before process CLI) this.errors = []; - this.on( 'error', function( msg, backtrace ){ + this.on( 'error', function pushErrorToStack( msg, backtrace ){ //this.debug( 'adding error to stack: ' + msg + ', trace:' + JSON.stringify( backtrace, null, 2 ) ); this.errors.push({ msg: msg, backtrace: backtrace }); }); @@ -187,6 +187,8 @@ //screenOnError : { defaultsTo: false, flag: 'error-screen', help: 'capture a screenshot on a page error' }, //textOnError : { defaultsTo: false, flag: 'error-text', help: 'output page text on a page error' }, //htmlOnError : { defaultsTo: false, flag: 'error-html', help: 'output page html on a page error' } + //htmlOnFail : { defaultsTo: false, flag: 'fail-html', help: 'output page html on a test failure' }, + //screenOnFail : { defaultsTo: false, flag: 'fail-screen', help: 'capture a screenshot on a test failure' } }; // --url parameter required (the url of the server to test with) @@ -196,17 +198,16 @@ } this.baseUrl = this.cli.get( 'url' ); + //TODO: move these handlers into _setUpEventHandlers // --return-json: supress all output except for JSON logs, test results, and errors at finish // this switch allows a testing suite to send JSON data back via stdout (w/o logs, echos interferring) this.options.returnJsonOnly = CLI_OPTIONS.returnJsonOnly.defaultsTo; if( this.cli.has( CLI_OPTIONS.returnJsonOnly.flag ) ){ this.options.returnJsonOnly = true; - //this._suppressOutput(); this._redirectOutputToStderr(); - // output json on fail-first error - this.on( 'error', function( msg, backtrace ){ + this.on( 'error', function outputJSONOnError( msg, backtrace ){ //console.debug( 'return-json caught error' ); if( spaceghost.options.exitOnError ){ this.outputStateAsJson(); @@ -216,6 +217,7 @@ // non-error finshes/json-output are handled in run() for now } + //TODO: remove boilerplate // --error-on-alert=false: don't throw an error if the page calls alert (default: true) this.options.raisePageError = CLI_OPTIONS.raisePageError.defaultsTo; if( this.cli.has( CLI_OPTIONS.raisePageError.flag ) ){ @@ -244,10 +246,13 @@ this.on( 'page.error', this._saveHtmlOnErrorHandler ); } - // --error-screen: print the casper.debugPage (the page's text) output on an error + // --error-screen: capture the casper browser screen on an error if( this.cli.has( 'error-screen' ) ){ this.on( 'page.error', this._saveScreenOnErrorHandler ); } + + // --fail-html: print the casper.debugHTML (the page's html) output on an test failure + // --fail-screen: print the casper browser screen output on an test failure */ // get any fixture data passed in as JSON in args @@ -457,16 +462,18 @@ //TODO: * @param {Boolean} removeOtherListeners option to remove other listeners while this fires // create three steps: 1) set up new error handler, 2) try the fn, 3) check for errors and rem. handler var originalExitOnError, + originalErrorHandlers = [], errorMsg = '', errorTrace = [], recordError = function( msg, trace ){ errorMsg = msg; errorTrace = trace; }; - // dont bail on the error (but preserve option), install hndlr to simply record msg, trace - //NOTE: haven't had to remove other listeners yet + // dont bail on the error (but preserve option), uninstall other handlers, + // and install hndlr to simply record msg, trace this.then( function(){ originalExitOnError = this.options.exitOnError; this.options.exitOnError = false; + originalErrorHandlers = this.popAllListeners( 'error' ); this.on( 'error', recordError ); }); @@ -478,12 +485,24 @@ if( errorMsg ){ catchFn.call( this, errorMsg, errorTrace ); } - // remove that listener either way and restore the bail option + // remove that listener either way, restore original handlers, and restore the bail option this.removeListener( 'error', recordError ); + this.addListeners( 'error', originalErrorHandlers ); this.options.exitOnError = originalExitOnError; }); }; +/** Override capture to save to environ: GALAXY_TEST_SAVE (or passed in from CLI) + * @param {String} filename the image filename + */ +SpaceGhost.prototype.capture = function capture( filename, clipRect_or_selector ){ + //TODO: override with saved output dir + if( clipRect_or_selector && ( !utils.isClipRect( clipRect_or_selector ) ) ){ + this.debug( "USING CAPTURE SELECTOR" ); + return this.captureSelector( filename, clipRect_or_selector ); + } + return Casper.prototype.capture.apply( this, arguments ); +}; // =================================================================== TESTING //TODO: form fill doesn't work as casperjs would want it - often a button -> controller url @@ -600,6 +619,25 @@ // =================================================================== GALAXY CONVENIENCE // =================================================================== MISCELAIN +/** Pop all handlers for eventName from casper and return them in order. + * @param {String} eventName the name of the event from which to remove handlers + */ +SpaceGhost.prototype.popAllListeners = function popAllListeners( eventName ){ + var returnedListeners = this.listeners( eventName ); + this.removeAllListeners( eventName ); + return returnedListeners; +}; + +/** Add the given list of handler functions to the listener for eventName in order. + * @param {String} eventName the name of the event to which to add handlers + * @param {Array} handlerArray an array of event handler functions to add + */ +SpaceGhost.prototype.addListeners = function addListeners( eventName, handlerArray ){ + for( var i=0; i<handlerArray.length; i++ ){ + this.addListener( eventName, handlerArray[i] ); + } +}; + /** Send message to stderr */ SpaceGhost.prototype.stderr = function( msg ){ Repository URL: https://bitbucket.org/galaxy/galaxy-central/ -- This is a commit notification from bitbucket.org. You are receiving this because you have the service enabled, addressing the recipient of this email.
participants (1)
-
commits-noreply@bitbucket.org