From c124086673eef1855ac4121a6798ca994e54b799 Mon Sep 17 00:00:00 2001 From: Mike Gerwitz Date: Fri, 5 Aug 2016 11:42:41 -0400 Subject: [PATCH] Correct and test GeneralStepUi#scrollTo * src/ui/step/GeneralStepUi.js (scrollTo): Will now abort after each error rather than falling through. Visibility error message will now show field index. * test/ui/step/GeneralStepUiTest.js: Added respective test cases --- src/ui/step/GeneralStepUi.js | 16 +- test/ui/step/GeneralStepUiTest.js | 255 +++++++++++++++++++++++++++++- 2 files changed, 260 insertions(+), 11 deletions(-) diff --git a/src/ui/step/GeneralStepUi.js b/src/ui/step/GeneralStepUi.js index 5153d4c..d7220fe 100644 --- a/src/ui/step/GeneralStepUi.js +++ b/src/ui/step/GeneralStepUi.js @@ -909,7 +909,7 @@ module.exports = Class( 'GeneralStepUi' ) { show_message = ( show_message === undefined ) ? true : !!show_message; - if ( !( field ) || ( i < 0 ) || i === undefined ) + if ( !field || ( i < 0 ) || ( i === undefined ) ) { // cause may be empty var cause = this.step.getValidCause(); @@ -923,19 +923,24 @@ module.exports = Class( 'GeneralStepUi' ) ) ) ); + + return this; } var index = this.styler.getProperIndex( field, i ), $element = this.styler.getWidgetByName( field, index ); // if the element couldn't be found, then this is useless - if ( $element.length == 0 ) + if ( $element.length === 0 ) { this.emit( 'error', Error( - 'Could not scroll: could not locate ' + field + '['+i+']' + 'Could not scroll: could not locate ' + + field + '[' + i + ']' ) ); + + return this; } // allow the groups to preprocess the scrolling @@ -950,8 +955,11 @@ module.exports = Class( 'GeneralStepUi' ) { // fail; don't bother scrolling this.emit( 'error', Error( - 'Could not scroll: element ' + field + ' is not visible' + 'Could not scroll: element ' + field + '[' + i + '] ' + + 'is not visible' ) ); + + return this; } // scroll to just above the first invalid question so that it diff --git a/test/ui/step/GeneralStepUiTest.js b/test/ui/step/GeneralStepUiTest.js index 01796d7..e16f2d8 100644 --- a/test/ui/step/GeneralStepUiTest.js +++ b/test/ui/step/GeneralStepUiTest.js @@ -46,7 +46,7 @@ describe( 'ui.GeneralStepUi', function() .withExactArgs( orig_data ) .returns( fmt_data ); - createSut( formatter, function( name, value ) + createSut( formatter, createElementStyler( function( name, value ) { // by the time the answer data makes its way to the // element styler, it should have already been @@ -56,7 +56,226 @@ describe( 'ui.GeneralStepUi', function() mock_fmt.verify(); done(); - } ).answerDataUpdate( orig_data ); + } ) ).answerDataUpdate( orig_data ); + } ); + } ); + + + describe( '#scrollTo', function() + { + [ + { + field: '', + index: 0, + cause: 'foocause', + }, + { + field: undefined, + index: 0, + cause: 'foocause2', + }, + { + field: '', + index: 0, + cause: '', + }, + { + field: '', + index: 0, + cause: undefined, + }, + { + field: 'foo', + index: -1, + cause: undefined, + }, + { + field: 'foo', + index: undefined, + cause: undefined, + }, + { + field: 'foo', + index: undefined, + cause: 'index cause', + }, + ].forEach( function( args, i ) + { + it( 'emits error given invalid field (' + i + ')', function( done ) + { + var step = { + getValidCause: function() + { + return args.cause; + } + }; + + var sut = createSut( {}, {}, step ); + + // should only throw a single error + sut.once( 'error', function( error ) + { + expect( error ).to.be.instanceof( Error ); + expect( error.message ).to.have.string( 'Could not scroll' ); + + if ( args.cause ) + { + expect( error.message ).to.have.string( 'cause: ' ); + expect( error.message ).to.have.string( args.cause ); + } + else + { + expect( error.message ).to.not.have.string( 'cause:' ); + } + + done(); + } ); + + sut.scrollTo( args.field, args.index, false, args.cause ); + } ); + } ); + + + it( 'emits error when element is not found', function( done ) + { + var field = 'foo', + index = 5; + + var styler = { + getProperIndex: function() + { + }, + + getWidgetByName: function() + { + // no element + return []; + }, + }; + + var sut = createSut( {}, styler, {} ); + + sut.once( 'error', function( error ) + { + expect( error ).to.be.instanceof( Error ); + expect( error.message ).to.have.string( 'Could not scroll' ); + expect( error.message ).to.have.string( 'could not locate' ); + + expect( error.message ).to.have.string( + field + '[' + index + ']' + ); + + done(); + } ); + + sut.scrollTo( field, index, false, '' ); + } ); + + + it( 'emits error when element is not visible', function( done ) + { + var field = 'foo', + index = 5; + + var styler = { + getProperIndex: function() + { + }, + + getWidgetByName: function() + { + // jQuery-ish + var element = [ 0 ]; + + element.is = function( selector ) + { + expect( selector ).to.equal( ':visible' ); + return false; + }; + + return element; + }, + }; + + var sut = createSut( {}, styler, {} ); + + sut.once( 'error', function( error ) + { + expect( error ).to.be.instanceof( Error ); + expect( error.message ).to.have.string( 'Could not scroll' ); + expect( error.message ).to.have.string( 'not visible' ); + + expect( error.message ).to.have.string( + field + '[' + index + ']' + ); + + done(); + } ); + + sut.scrollTo( field, index, false, '' ); + } ); + + + it( 'scrolls to the failed element', function( done ) + { + var field = 'foo', + index = 5, + content_html = 'something', + element = [ 0 ], + showm = true, + message = 'whatacluster'; + + var styler = { + getProperIndex: function() + { + }, + + getWidgetByName: function() + { + element.is = function( selector ) + { + expect( selector ).to.equal( ':visible' ); + return true; + }; + + return element; + }, + }; + + var content = { + parent: function() + { + return { + scrollTo: scroll_mock + }; + }, + }; + + function scroll_mock( given_element, duration, options ) + { + expect( given_element ).to.equal( element ); + expect( duration ).to.equal( 100 ); + expect( options.offset.top ).to.equal( -150 ); + + styler.focus = function( given_element, given_showm, given_msg ) + { + expect( given_element ).to.equal( element ); + expect( given_showm ).to.equal( showm ); + expect( given_msg ).to.equal( message ); + + done(); + }; + + options.onAfter(); + }; + + var sut = createSut( {}, styler, {} ); + + // XXX: SUT needs refactoring! + sut.$content = content; + + var result = sut.scrollTo( field, index, true, message ); + expect( result ).to.equal( sut ); } ); } ); } ); @@ -67,12 +286,13 @@ describe( 'ui.GeneralStepUi', function() * Create new SUT with formatter FORMATTER and generated element * styler * - * @param {Object} formatter validator/formatter mock - * @param {function(string,*)} style_callback styler styleAnswer method dfn + * @param {Object} formatter validator/formatter mock + * @param {Object} styler mock ElementStyler + * @param {Object} step mock step * * @return {Sut} */ -function createSut( formatter, style_callback ) +function createSut( formatter, styler, step ) { return Sut.extend( { @@ -87,8 +307,8 @@ function createSut( formatter, style_callback ) return {}; }, } )( - {}, - createElementStyler( style_callback ), + step || {}, + styler, formatter ); } @@ -99,6 +319,8 @@ function createSut( formatter, style_callback ) * * styleAnswer method is defined by STYLE_CALLBACK * + * @param {function(string,*)} style_callback styler styleAnswer method dfn + * * @return {Object} ElementStyler mock */ function createElementStyler( style_callback ) @@ -115,6 +337,15 @@ function createElementStyler( style_callback ) } }, + getProperIndex: function() + { + }, + + getWidgetByName: function() + { + return []; + }, + styleAnswer: style_callback, }; } @@ -136,3 +367,13 @@ function createFormatter( expected, return_data ) }, } } + + +function createStep() +{ + return { + getValidCause: function() + { + } + }; +}